/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { /// /// Extension methods for /// public static class IFindFluentExtensions { /// /// Projects the result. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The projection. /// The fluent find interface. public static IFindFluent Project(this IFindFluent find, ProjectionDefinition projection) { Ensure.IsNotNull(find, nameof(find)); Ensure.IsNotNull(projection, nameof(projection)); return find.Project(projection); } /// /// Projects the result. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The type of the new projection. /// The fluent find. /// The projection. /// The fluent find interface. public static IFindFluent Project(this IFindFluent find, Expression> projection) { Ensure.IsNotNull(find, nameof(find)); Ensure.IsNotNull(projection, nameof(projection)); return find.Project(new FindExpressionProjectionDefinition(projection)); } /// /// Sorts the results by an ascending field. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The field. /// The fluent find interface. public static IOrderedFindFluent SortBy(this IFindFluent find, Expression> field) { Ensure.IsNotNull(find, nameof(find)); Ensure.IsNotNull(field, nameof(field)); // We require an implementation of IFindFluent // to also implement IOrderedFindFluent return (IOrderedFindFluent)find.Sort( new DirectionalSortDefinition(new ExpressionFieldDefinition(field), SortDirection.Ascending)); } /// /// Sorts the results by a descending field. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The field. /// The fluent find interface. public static IOrderedFindFluent SortByDescending(this IFindFluent find, Expression> field) { Ensure.IsNotNull(find, nameof(find)); Ensure.IsNotNull(field, nameof(field)); // We require an implementation of IFindFluent // to also implement IOrderedFindFluent return (IOrderedFindFluent)find.Sort( new DirectionalSortDefinition(new ExpressionFieldDefinition(field), SortDirection.Descending)); } /// /// Adds an ascending field to the existing sort. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The field. /// The fluent find interface. public static IOrderedFindFluent ThenBy(this IOrderedFindFluent find, Expression> field) { Ensure.IsNotNull(find, nameof(find)); Ensure.IsNotNull(field, nameof(field)); find.Options.Sort = new SortDefinitionBuilder().Combine( find.Options.Sort, new DirectionalSortDefinition(new ExpressionFieldDefinition(field), SortDirection.Ascending)); return find; } /// /// Adds a descending field to the existing sort. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The field. /// The fluent find interface. public static IOrderedFindFluent ThenByDescending(this IOrderedFindFluent find, Expression> field) { Ensure.IsNotNull(find, nameof(find)); Ensure.IsNotNull(field, nameof(field)); find.Options.Sort = new SortDefinitionBuilder().Combine( find.Options.Sort, new DirectionalSortDefinition(new ExpressionFieldDefinition(field), SortDirection.Descending)); return find; } /// /// Get the first result. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the first result. public static TProjection First(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); return IAsyncCursorSourceExtensions.First(find.Limit(1), cancellationToken); } /// /// Get the first result. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the first result. public static Task FirstAsync(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); return IAsyncCursorSourceExtensions.FirstAsync(find.Limit(1), cancellationToken); } /// /// Get the first result or null. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the first result or null. public static TProjection FirstOrDefault(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); return IAsyncCursorSourceExtensions.FirstOrDefault(find.Limit(1), cancellationToken); } /// /// Get the first result or null. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the first result or null. public static Task FirstOrDefaultAsync(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); return IAsyncCursorSourceExtensions.FirstOrDefaultAsync(find.Limit(1), cancellationToken); } /// /// Gets a single result. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the single result. public static TProjection Single(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); if (!find.Options.Limit.HasValue || find.Options.Limit.Value > 2) { find = find.Limit(2); } return IAsyncCursorSourceExtensions.Single(find, cancellationToken); } /// /// Gets a single result. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the single result. public static Task SingleAsync(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); if (!find.Options.Limit.HasValue || find.Options.Limit.Value > 2) { find = find.Limit(2); } return IAsyncCursorSourceExtensions.SingleAsync(find, cancellationToken); } /// /// Gets a single result or null. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the single result or null. public static TProjection SingleOrDefault(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); if (!find.Options.Limit.HasValue || find.Options.Limit.Value > 2) { find = find.Limit(2); } return IAsyncCursorSourceExtensions.SingleOrDefault(find, cancellationToken); } /// /// Gets a single result or null. /// /// The type of the document. /// The type of the projection (same as TDocument if there is no projection). /// The fluent find. /// The cancellation token. /// A Task whose result is the single result or null. public static Task SingleOrDefaultAsync(this IFindFluent find, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.IsNotNull(find, nameof(find)); if (!find.Options.Limit.HasValue || find.Options.Limit.Value > 2) { find = find.Limit(2); } return IAsyncCursorSourceExtensions.SingleOrDefaultAsync(find, cancellationToken); } } }