/* Copyright 2016-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.Collections.Generic; using System.Linq; using System.Linq.Expressions; using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver { /// /// Extension methods for adding stages to a pipeline. /// public static class PipelineDefinitionBuilder { /// /// Appends a stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The stage. /// The output serializer. /// A new pipeline with an additional stage. public static PipelineDefinition AppendStage( this PipelineDefinition pipeline, PipelineStageDefinition stage, IBsonSerializer outputSerializer = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); Ensure.IsNotNull(stage, nameof(stage)); return new AppendedStagePipelineDefinition(pipeline, stage, outputSerializer); } /// /// Changes the output type of the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The output serializer. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition As( this PipelineDefinition pipeline, IBsonSerializer outputSerializer = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return new ReplaceOutputSerializerPipelineDefinition(pipeline, outputSerializer); } /// /// Appends a $bucket stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The pipeline. /// The group by expression. /// The boundaries. /// The options. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition> Bucket( this PipelineDefinition pipeline, AggregateExpressionDefinition groupBy, IEnumerable boundaries, AggregateBucketOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, options)); } /// /// Appends a $bucket stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The type of the output documents. /// The pipeline. /// The group by expression. /// The boundaries. /// The output projection. /// The options. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Bucket( this PipelineDefinition pipeline, AggregateExpressionDefinition groupBy, IEnumerable boundaries, ProjectionDefinition output, AggregateBucketOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, output, options)); } /// /// Appends a $bucket stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The pipeline. /// The group by expression. /// The boundaries. /// The options. /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition> Bucket( this PipelineDefinition pipeline, Expression> groupBy, IEnumerable boundaries, AggregateBucketOptions options = null, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, options, translationOptions)); } /// /// Appends a $bucket stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The type of the output documents. /// The pipeline. /// The group by expression. /// The boundaries. /// The output projection. /// The options. /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition Bucket( this PipelineDefinition pipeline, Expression> groupBy, IEnumerable boundaries, Expression, TOutput>> output, AggregateBucketOptions options = null, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, output, options, translationOptions)); } /// /// Appends a $bucketAuto stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The pipeline. /// The group by expression. /// The number of buckets. /// The options. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition> BucketAuto( this PipelineDefinition pipeline, AggregateExpressionDefinition groupBy, int buckets, AggregateBucketAutoOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, options)); } /// /// Appends a $bucketAuto stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The type of the output documents. /// The pipeline. /// The group by expression. /// The number of buckets. /// The output projection. /// The options. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition BucketAuto( this PipelineDefinition pipeline, AggregateExpressionDefinition groupBy, int buckets, ProjectionDefinition output, AggregateBucketAutoOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, output, options)); } /// /// Appends a $bucketAuto stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the value. /// The pipeline. /// The group by expression. /// The number of buckets. /// The options (optional). /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition> BucketAuto( this PipelineDefinition pipeline, Expression> groupBy, int buckets, AggregateBucketAutoOptions options = null, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, options, translationOptions)); } /// /// Appends a $bucketAuto stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the value. /// The type of the output documents. /// The pipeline. /// The group by expression. /// The number of buckets. /// The output projection. /// The options (optional). /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition BucketAuto( this PipelineDefinition pipeline, Expression> groupBy, int buckets, Expression, TOutput>> output, AggregateBucketAutoOptions options = null, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, output, options, translationOptions)); } /// /// Appends a $changeStream stage to the pipeline. /// Normally you would prefer to use the Watch method of . /// Only use this method if subsequent stages project away the resume token (the _id) /// or you don't want the resulting cursor to automatically resume. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// The options. /// /// The fluent aggregate interface. /// public static PipelineDefinition> ChangeStream( this PipelineDefinition pipeline, ChangeStreamStageOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.ChangeStream(options)); } /// /// Appends a $count stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Count( this PipelineDefinition pipeline) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Count()); } /// /// Appends a $facet stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The facets. /// The options. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Facet( this PipelineDefinition pipeline, IEnumerable> facets, AggregateFacetOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets, options)); } /// /// Appends a $facet stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// The facets. /// /// The fluent aggregate interface. /// public static PipelineDefinition Facet( this PipelineDefinition pipeline, IEnumerable> facets) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets)); } /// /// Appends a $facet stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// The facets. /// /// The fluent aggregate interface. /// public static PipelineDefinition Facet( this PipelineDefinition pipeline, params AggregateFacet[] facets) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets)); } /// /// Appends a $facet stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The facets. /// /// The fluent aggregate interface. /// public static PipelineDefinition Facet( this PipelineDefinition pipeline, params AggregateFacet[] facets) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets)); } /// /// Used to start creating a pipeline for {TInput} documents. /// /// The type of the output. /// The inputSerializer serializer. /// /// The fluent aggregate interface. /// public static PipelineDefinition For(IBsonSerializer inputSerializer = null) { return new EmptyPipelineDefinition(inputSerializer); } /// /// Appends a $graphLookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the from documents. /// The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the connect to field. /// The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the as field elements. /// The type of the as field. /// The type of the output documents. /// The pipeline. /// The from collection. /// The connect from field. /// The connect to field. /// The start with value. /// The as field. /// The depth field. /// The options. /// The fluent aggregate interface. public static PipelineDefinition GraphLookup( this PipelineDefinition pipeline, IMongoCollection from, FieldDefinition connectFromField, FieldDefinition connectToField, AggregateExpressionDefinition startWith, FieldDefinition @as, FieldDefinition depthField, AggregateGraphLookupOptions options = null) where TAs : IEnumerable { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField, options)); } /// /// Appends a $graphLookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the from documents. /// The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the connect to field. /// The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the as field. /// The type of the output documents. /// The pipeline. /// The from collection. /// The connect from field. /// The connect to field. /// The start with value. /// The as field. /// The options. /// The stage. public static PipelineDefinition GraphLookup( this PipelineDefinition pipeline, IMongoCollection from, FieldDefinition connectFromField, FieldDefinition connectToField, AggregateExpressionDefinition startWith, FieldDefinition @as, AggregateGraphLookupOptions options = null) where TAs : IEnumerable { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, options)); } /// /// Appends a $graphLookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the from documents. /// The pipeline. /// The from collection. /// The connect from field. /// The connect to field. /// The start with value. /// The as field. /// The depth field. /// The fluent aggregate interface. public static PipelineDefinition GraphLookup( this PipelineDefinition pipeline, IMongoCollection from, FieldDefinition connectFromField, FieldDefinition connectToField, AggregateExpressionDefinition startWith, FieldDefinition> @as, FieldDefinition depthField = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField)); } /// /// Appends a $graphLookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the from documents. /// The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the connect to field. /// The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the as field. /// The type of the output documents. /// The pipeline. /// The from collection. /// The connect from field. /// The connect to field. /// The start with value. /// The as field. /// The options. /// The translation options. /// The stage. public static PipelineDefinition GraphLookup( this PipelineDefinition pipeline, IMongoCollection from, Expression> connectFromField, Expression> connectToField, Expression> startWith, Expression> @as, AggregateGraphLookupOptions options = null, ExpressionTranslationOptions translationOptions = null) where TAs : IEnumerable { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, options, translationOptions)); } /// /// Appends a $graphLookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the from documents. /// The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the connect to field. /// The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}). /// The type of the as field elements. /// The type of the as field. /// The type of the output documents. /// The pipeline. /// The from collection. /// The connect from field. /// The connect to field. /// The start with value. /// The as field. /// The depth field. /// The options. /// The translation options. /// The stage. public static PipelineDefinition GraphLookup( this PipelineDefinition pipeline, IMongoCollection from, Expression> connectFromField, Expression> connectToField, Expression> startWith, Expression> @as, Expression> depthField, AggregateGraphLookupOptions options = null, ExpressionTranslationOptions translationOptions = null) where TAs : IEnumerable { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField, options, translationOptions)); } /// /// Appends a $group stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The group projection. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Group( this PipelineDefinition pipeline, ProjectionDefinition group) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(group)); } /// /// Appends a group stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// The group projection. /// /// The fluent aggregate interface. /// public static PipelineDefinition Group( this PipelineDefinition pipeline, ProjectionDefinition group) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(group)); } /// /// Appends a group stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the key. /// The type of the output documents. /// The pipeline. /// The id. /// The group projection. /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition Group( this PipelineDefinition pipeline, Expression> id, Expression, TOutput>> group, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(id, group, translationOptions)); } /// /// Appends a $limit stage to the pipeline. /// /// The type of the input documents. /// The type of the output documents. /// The pipeline. /// The limit. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Limit( this PipelineDefinition pipeline, int limit) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Limit(limit)); } /// /// Appends a $lookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the foreign collection documents. /// The type of the output documents. /// The pipeline. /// The foreign collection. /// The local field. /// The foreign field. /// The "as" field. /// The options. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Lookup( this PipelineDefinition pipeline, IMongoCollection foreignCollection, FieldDefinition localField, FieldDefinition foreignField, FieldDefinition @as, AggregateLookupOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup(foreignCollection, localField, foreignField, @as, options)); } /// /// Appends a lookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the foreign collection documents. /// The type of the output documents. /// The pipeline. /// The foreign collection. /// The local field. /// The foreign field. /// The "as" field. /// The options. /// /// The fluent aggregate interface. /// public static PipelineDefinition Lookup( this PipelineDefinition pipeline, IMongoCollection foreignCollection, Expression> localField, Expression> foreignField, Expression> @as, AggregateLookupOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup(foreignCollection, localField, foreignField, @as, options)); } /// /// Appends a $lookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the foreign collection documents. /// The type of the as field elements. /// The type of the as field. /// The type of the output documents. /// The pipeline. /// The foreign collection. /// The "let" definition. /// The lookup pipeline. /// The as field in in which to place the results of the lookup pipeline. /// The options. /// The stage. public static PipelineDefinition Lookup( this PipelineDefinition pipeline, IMongoCollection foreignCollection, BsonDocument let, PipelineDefinition lookupPipeline, FieldDefinition @as, AggregateLookupOptions options = null) where TAs : IEnumerable { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup( foreignCollection, let, lookupPipeline, @as, options )); } /// /// Appends a $lookup stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the foreign collection documents. /// The type of the as field elements. /// The type of the as field. /// The type of the output documents. /// The pipeline. /// The foreign collection. /// The "let" definition. /// The lookup pipeline. /// The as field in in which to place the results of the lookup pipeline. /// The options. /// The stage. public static PipelineDefinition Lookup( this PipelineDefinition pipeline, IMongoCollection foreignCollection, BsonDocument let, PipelineDefinition lookupPipeline, Expression> @as, AggregateLookupOptions options = null) where TAs : IEnumerable { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup( foreignCollection, let, lookupPipeline, @as, options )); } /// /// Appends a $match stage to the pipeline. /// /// The type of the input documents. /// The type of the output documents. /// The pipeline. /// The filter. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Match( this PipelineDefinition pipeline, FilterDefinition filter) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Match(filter)); } /// /// Appends a match stage to the pipeline. /// /// The type of the input documents. /// The type of the output documents. /// The pipeline. /// The filter. /// /// The fluent aggregate interface. /// public static PipelineDefinition Match( this PipelineDefinition pipeline, Expression> filter) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Match(filter)); } /// /// Appends a $match stage to the pipeline to select documents of a certain type. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The output serializer. /// /// A new pipeline with an additional stage. /// /// public static PipelineDefinition OfType( this PipelineDefinition pipeline, IBsonSerializer outputSerializer = null) where TOutput : TIntermediate { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.OfType(outputSerializer)); } /// /// Appends a $out stage to the pipeline. /// /// The type of the input documents. /// The type of the output documents. /// The pipeline. /// The output collection. /// /// A new pipeline with an additional stage. /// /// public static PipelineDefinition Out( this PipelineDefinition pipeline, IMongoCollection outputCollection) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Out(outputCollection)); } /// /// Appends a $project stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The projection. /// /// A new pipeline with an additional stage. /// /// public static PipelineDefinition Project( this PipelineDefinition pipeline, ProjectionDefinition projection) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection)); } /// /// Appends a project stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// The projection. /// /// The fluent aggregate interface. /// public static PipelineDefinition Project( this PipelineDefinition pipeline, ProjectionDefinition projection) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection)); } /// /// Appends a project stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The projection. /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition Project( this PipelineDefinition pipeline, Expression> projection, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection, translationOptions)); } /// /// Appends a $replaceRoot stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The new root. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition ReplaceRoot( this PipelineDefinition pipeline, AggregateExpressionDefinition newRoot) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.ReplaceRoot(newRoot)); } /// /// Appends a $replaceRoot stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The new root. /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition ReplaceRoot( this PipelineDefinition pipeline, Expression> newRoot, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.ReplaceRoot(newRoot, translationOptions)); } /// /// Appends a $skip stage to the pipeline. /// /// The type of the input documents. /// The type of the output documents. /// The pipeline. /// The number of documents to skip. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Skip( this PipelineDefinition pipeline, int skip) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Skip(skip)); } /// /// Appends a $sort stage to the pipeline. /// /// The type of the input documents. /// The type of the output documents. /// The pipeline. /// The sort definition. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Sort( this PipelineDefinition pipeline, SortDefinition sort) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Sort(sort)); } /// /// Appends a $sortByCount stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The pipeline. /// The value expression. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition> SortByCount( this PipelineDefinition pipeline, AggregateExpressionDefinition value) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.SortByCount(value)); } /// /// Appends a sortByCount stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the values. /// The pipeline. /// The value expression. /// The translation options. /// /// The fluent aggregate interface. /// public static PipelineDefinition> SortByCount( this PipelineDefinition pipeline, Expression> value, ExpressionTranslationOptions translationOptions = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.SortByCount(value, translationOptions)); } /// /// Appends an $unwind stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The field. /// The options. /// /// A new pipeline with an additional stage. /// public static PipelineDefinition Unwind( this PipelineDefinition pipeline, FieldDefinition field, AggregateUnwindOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options)); } /// /// Appends an unwind stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// The field to unwind. /// The options. /// /// The fluent aggregate interface. /// public static PipelineDefinition Unwind( this PipelineDefinition pipeline, FieldDefinition field, AggregateUnwindOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options)); } /// /// Appends an unwind stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The pipeline. /// The field to unwind. /// The options. /// /// The fluent aggregate interface. /// public static PipelineDefinition Unwind( this PipelineDefinition pipeline, Expression> field, AggregateUnwindOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options)); } /// /// Appends an unwind stage to the pipeline. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// The pipeline. /// The field to unwind. /// The options. /// /// The fluent aggregate interface. /// public static PipelineDefinition Unwind( this PipelineDefinition pipeline, Expression> field, AggregateUnwindOptions options = null) { Ensure.IsNotNull(pipeline, nameof(pipeline)); return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options)); } } /// /// Represents a pipeline consisting of an existing pipeline with one additional stage appended. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. public sealed class AppendedStagePipelineDefinition : PipelineDefinition { private readonly IBsonSerializer _outputSerializer; private readonly PipelineDefinition _pipeline; private readonly PipelineStageDefinition _stage; /// /// Initializes a new instance of the class. /// /// The pipeline. /// The stage. /// The output serializer. public AppendedStagePipelineDefinition( PipelineDefinition pipeline, PipelineStageDefinition stage, IBsonSerializer outputSerializer = null) { _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline)); _stage = Ensure.IsNotNull(stage, nameof(stage)); _outputSerializer = outputSerializer; // can be null } /// public override IBsonSerializer OutputSerializer => _outputSerializer; /// public override IEnumerable Stages => _pipeline.Stages.Concat(new[] { _stage }); /// public override RenderedPipelineDefinition Render(IBsonSerializer inputSerializer, IBsonSerializerRegistry serializerRegistry) { var renderedPipeline = _pipeline.Render(inputSerializer, serializerRegistry); var renderedStage = _stage.Render(renderedPipeline.OutputSerializer, serializerRegistry); var documents = renderedPipeline.Documents.Concat(new[] { renderedStage.Document }); var outputSerializer = _outputSerializer ?? renderedStage.OutputSerializer; return new RenderedPipelineDefinition(documents, outputSerializer); } } /// /// Represents an empty pipeline. /// /// The type of the input documents. public sealed class EmptyPipelineDefinition : PipelineDefinition { private readonly IBsonSerializer _inputSerializer; /// /// Initializes a new instance of the class. /// /// The output serializer. public EmptyPipelineDefinition(IBsonSerializer inputSerializer = null) { _inputSerializer = inputSerializer; // can be null } /// public override IBsonSerializer OutputSerializer => _inputSerializer; /// public override IEnumerable Stages => Enumerable.Empty(); /// public override RenderedPipelineDefinition Render(IBsonSerializer inputSerializer, IBsonSerializerRegistry serializerRegistry) { var documents = Enumerable.Empty(); return new RenderedPipelineDefinition(documents, _inputSerializer ?? inputSerializer); } } /// /// Represents a pipeline consisting of an existing pipeline with one additional stage prepended. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. public sealed class PrependedStagePipelineDefinition : PipelineDefinition { private readonly IBsonSerializer _outputSerializer; private readonly PipelineDefinition _pipeline; private readonly PipelineStageDefinition _stage; /// /// Initializes a new instance of the class. /// /// The stage. /// The pipeline. /// The output serializer. public PrependedStagePipelineDefinition( PipelineStageDefinition stage, PipelineDefinition pipeline, IBsonSerializer outputSerializer = null) { _stage = Ensure.IsNotNull(stage, nameof(stage)); _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline)); _outputSerializer = outputSerializer; // can be null } /// public override IBsonSerializer OutputSerializer => _outputSerializer; /// public override IEnumerable Stages => new[] { _stage }.Concat(_pipeline.Stages); /// public override RenderedPipelineDefinition Render(IBsonSerializer inputSerializer, IBsonSerializerRegistry serializerRegistry) { var renderedStage = _stage.Render(inputSerializer, serializerRegistry); var renderedPipeline = _pipeline.Render(renderedStage.OutputSerializer, serializerRegistry); var documents = new[] { renderedStage.Document }.Concat(renderedPipeline.Documents); var outputSerializer = _outputSerializer ?? renderedPipeline.OutputSerializer; return new RenderedPipelineDefinition(documents, outputSerializer); } } /// /// Represents a pipeline with the output serializer replaced. /// /// The type of the input documents. /// The type of the intermediate documents. /// The type of the output documents. /// public sealed class ReplaceOutputSerializerPipelineDefinition : PipelineDefinition { private readonly IBsonSerializer _outputSerializer; private readonly PipelineDefinition _pipeline; /// /// Initializes a new instance of the class. /// /// The pipeline. /// The output serializer. public ReplaceOutputSerializerPipelineDefinition( PipelineDefinition pipeline, IBsonSerializer outputSerializer = null) { _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline)); _outputSerializer = outputSerializer; // can be null } /// public override IBsonSerializer OutputSerializer => _outputSerializer; /// public override IEnumerable Stages => _pipeline.Stages; /// public override RenderedPipelineDefinition Render(IBsonSerializer inputSerializer, IBsonSerializerRegistry serializerRegistry) { var renderedPipeline = _pipeline.Render(inputSerializer, serializerRegistry); var outputSerializer = _outputSerializer ?? serializerRegistry.GetSerializer(); return new RenderedPipelineDefinition(renderedPipeline.Documents, outputSerializer); } } }