PipelineDefinitionBuilder.cs 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. /* Copyright 2016 MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Linq;
  18. using System.Linq.Expressions;
  19. using MongoDB.Bson;
  20. using MongoDB.Bson.Serialization;
  21. using MongoDB.Driver.Core.Misc;
  22. namespace MongoDB.Driver
  23. {
  24. /// <summary>
  25. /// Extension methods for adding stages to a pipeline.
  26. /// </summary>
  27. public static class PipelineDefinitionBuilder
  28. {
  29. /// <summary>
  30. /// Appends a stage to the pipeline.
  31. /// </summary>
  32. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  33. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  34. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  35. /// <param name="pipeline">The pipeline.</param>
  36. /// <param name="stage">The stage.</param>
  37. /// <param name="outputSerializer">The output serializer.</param>
  38. /// <returns>A new pipeline with an additional stage.</returns>
  39. public static PipelineDefinition<TInput, TOutput> AppendStage<TInput, TIntermediate, TOutput>(
  40. this PipelineDefinition<TInput, TIntermediate> pipeline,
  41. PipelineStageDefinition<TIntermediate, TOutput> stage,
  42. IBsonSerializer<TOutput> outputSerializer = null)
  43. {
  44. Ensure.IsNotNull(pipeline, nameof(pipeline));
  45. Ensure.IsNotNull(stage, nameof(stage));
  46. return new AppendedStagePipelineDefinition<TInput, TIntermediate, TOutput>(pipeline, stage, outputSerializer);
  47. }
  48. /// <summary>
  49. /// Changes the output type of the pipeline.
  50. /// </summary>
  51. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  52. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  53. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  54. /// <param name="pipeline">The pipeline.</param>
  55. /// <param name="outputSerializer">The output serializer.</param>
  56. /// <returns>
  57. /// A new pipeline with an additional stage.
  58. /// </returns>
  59. public static PipelineDefinition<TInput, TOutput> As<TInput, TIntermediate, TOutput>(
  60. this PipelineDefinition<TInput, TIntermediate> pipeline,
  61. IBsonSerializer<TOutput> outputSerializer = null)
  62. {
  63. Ensure.IsNotNull(pipeline, nameof(pipeline));
  64. return new ReplaceOutputSerializerPipelineDefinition<TInput, TIntermediate, TOutput>(pipeline, outputSerializer);
  65. }
  66. /// <summary>
  67. /// Appends a $bucket stage to the pipeline.
  68. /// </summary>
  69. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  70. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  71. /// <typeparam name="TValue">The type of the values.</typeparam>
  72. /// <param name="pipeline">The pipeline.</param>
  73. /// <param name="groupBy">The group by expression.</param>
  74. /// <param name="boundaries">The boundaries.</param>
  75. /// <param name="options">The options.</param>
  76. /// <returns>
  77. /// A new pipeline with an additional stage.
  78. /// </returns>
  79. public static PipelineDefinition<TInput, AggregateBucketResult<TValue>> Bucket<TInput, TIntermediate, TValue>(
  80. this PipelineDefinition<TInput, TIntermediate> pipeline,
  81. AggregateExpressionDefinition<TIntermediate, TValue> groupBy,
  82. IEnumerable<TValue> boundaries,
  83. AggregateBucketOptions<TValue> options = null)
  84. {
  85. Ensure.IsNotNull(pipeline, nameof(pipeline));
  86. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, options));
  87. }
  88. /// <summary>
  89. /// Appends a $bucket stage to the pipeline.
  90. /// </summary>
  91. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  92. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  93. /// <typeparam name="TValue">The type of the values.</typeparam>
  94. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  95. /// <param name="pipeline">The pipeline.</param>
  96. /// <param name="groupBy">The group by expression.</param>
  97. /// <param name="boundaries">The boundaries.</param>
  98. /// <param name="output">The output projection.</param>
  99. /// <param name="options">The options.</param>
  100. /// <returns>
  101. /// A new pipeline with an additional stage.
  102. /// </returns>
  103. public static PipelineDefinition<TInput, TOutput> Bucket<TInput, TIntermediate, TValue, TOutput>(
  104. this PipelineDefinition<TInput, TIntermediate> pipeline,
  105. AggregateExpressionDefinition<TIntermediate, TValue> groupBy,
  106. IEnumerable<TValue> boundaries,
  107. ProjectionDefinition<TIntermediate, TOutput> output,
  108. AggregateBucketOptions<TValue> options = null)
  109. {
  110. Ensure.IsNotNull(pipeline, nameof(pipeline));
  111. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, output, options));
  112. }
  113. /// <summary>
  114. /// Appends a $bucket stage to the pipeline.
  115. /// </summary>
  116. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  117. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  118. /// <typeparam name="TValue">The type of the values.</typeparam>
  119. /// <param name="pipeline">The pipeline.</param>
  120. /// <param name="groupBy">The group by expression.</param>
  121. /// <param name="boundaries">The boundaries.</param>
  122. /// <param name="options">The options.</param>
  123. /// <param name="translationOptions">The translation options.</param>
  124. /// <returns>
  125. /// The fluent aggregate interface.
  126. /// </returns>
  127. public static PipelineDefinition<TInput, AggregateBucketResult<TValue>> Bucket<TInput, TIntermediate, TValue>(
  128. this PipelineDefinition<TInput, TIntermediate> pipeline,
  129. Expression<Func<TIntermediate, TValue>> groupBy,
  130. IEnumerable<TValue> boundaries,
  131. AggregateBucketOptions<TValue> options = null,
  132. ExpressionTranslationOptions translationOptions = null)
  133. {
  134. Ensure.IsNotNull(pipeline, nameof(pipeline));
  135. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, options, translationOptions));
  136. }
  137. /// <summary>
  138. /// Appends a $bucket stage to the pipeline.
  139. /// </summary>
  140. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  141. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  142. /// <typeparam name="TValue">The type of the values.</typeparam>
  143. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  144. /// <param name="pipeline">The pipeline.</param>
  145. /// <param name="groupBy">The group by expression.</param>
  146. /// <param name="boundaries">The boundaries.</param>
  147. /// <param name="output">The output projection.</param>
  148. /// <param name="options">The options.</param>
  149. /// <param name="translationOptions">The translation options.</param>
  150. /// <returns>
  151. /// The fluent aggregate interface.
  152. /// </returns>
  153. public static PipelineDefinition<TInput, TOutput> Bucket<TInput, TIntermediate, TValue, TOutput>(
  154. this PipelineDefinition<TInput, TIntermediate> pipeline,
  155. Expression<Func<TIntermediate, TValue>> groupBy,
  156. IEnumerable<TValue> boundaries,
  157. Expression<Func<IGrouping<TValue, TIntermediate>, TOutput>> output,
  158. AggregateBucketOptions<TValue> options = null,
  159. ExpressionTranslationOptions translationOptions = null)
  160. {
  161. Ensure.IsNotNull(pipeline, nameof(pipeline));
  162. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, output, options, translationOptions));
  163. }
  164. /// <summary>
  165. /// Appends a $bucketAuto stage to the pipeline.
  166. /// </summary>
  167. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  168. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  169. /// <typeparam name="TValue">The type of the values.</typeparam>
  170. /// <param name="pipeline">The pipeline.</param>
  171. /// <param name="groupBy">The group by expression.</param>
  172. /// <param name="buckets">The number of buckets.</param>
  173. /// <param name="options">The options.</param>
  174. /// <returns>
  175. /// A new pipeline with an additional stage.
  176. /// </returns>
  177. public static PipelineDefinition<TInput, AggregateBucketAutoResult<TValue>> BucketAuto<TInput, TIntermediate, TValue>(
  178. this PipelineDefinition<TInput, TIntermediate> pipeline,
  179. AggregateExpressionDefinition<TIntermediate, TValue> groupBy,
  180. int buckets,
  181. AggregateBucketAutoOptions options = null)
  182. {
  183. Ensure.IsNotNull(pipeline, nameof(pipeline));
  184. return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, options));
  185. }
  186. /// <summary>
  187. /// Appends a $bucketAuto stage to the pipeline.
  188. /// </summary>
  189. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  190. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  191. /// <typeparam name="TValue">The type of the values.</typeparam>
  192. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  193. /// <param name="pipeline">The pipeline.</param>
  194. /// <param name="groupBy">The group by expression.</param>
  195. /// <param name="buckets">The number of buckets.</param>
  196. /// <param name="output">The output projection.</param>
  197. /// <param name="options">The options.</param>
  198. /// <returns>
  199. /// A new pipeline with an additional stage.
  200. /// </returns>
  201. public static PipelineDefinition<TInput, TOutput> BucketAuto<TInput, TIntermediate, TValue, TOutput>(
  202. this PipelineDefinition<TInput, TIntermediate> pipeline,
  203. AggregateExpressionDefinition<TIntermediate, TValue> groupBy,
  204. int buckets,
  205. ProjectionDefinition<TIntermediate, TOutput> output,
  206. AggregateBucketAutoOptions options = null)
  207. {
  208. Ensure.IsNotNull(pipeline, nameof(pipeline));
  209. return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, output, options));
  210. }
  211. /// <summary>
  212. /// Appends a $bucketAuto stage to the pipeline.
  213. /// </summary>
  214. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  215. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  216. /// <typeparam name="TValue">The type of the value.</typeparam>
  217. /// <param name="pipeline">The pipeline.</param>
  218. /// <param name="groupBy">The group by expression.</param>
  219. /// <param name="buckets">The number of buckets.</param>
  220. /// <param name="options">The options (optional).</param>
  221. /// <param name="translationOptions">The translation options.</param>
  222. /// <returns>
  223. /// The fluent aggregate interface.
  224. /// </returns>
  225. public static PipelineDefinition<TInput, AggregateBucketAutoResult<TValue>> BucketAuto<TInput, TIntermediate, TValue>(
  226. this PipelineDefinition<TInput, TIntermediate> pipeline,
  227. Expression<Func<TIntermediate, TValue>> groupBy,
  228. int buckets,
  229. AggregateBucketAutoOptions options = null,
  230. ExpressionTranslationOptions translationOptions = null)
  231. {
  232. Ensure.IsNotNull(pipeline, nameof(pipeline));
  233. return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, options, translationOptions));
  234. }
  235. /// <summary>
  236. /// Appends a $bucketAuto stage to the pipeline.
  237. /// </summary>
  238. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  239. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  240. /// <typeparam name="TValue">The type of the value.</typeparam>
  241. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  242. /// <param name="pipeline">The pipeline.</param>
  243. /// <param name="groupBy">The group by expression.</param>
  244. /// <param name="buckets">The number of buckets.</param>
  245. /// <param name="output">The output projection.</param>
  246. /// <param name="options">The options (optional).</param>
  247. /// <param name="translationOptions">The translation options.</param>
  248. /// <returns>
  249. /// The fluent aggregate interface.
  250. /// </returns>
  251. public static PipelineDefinition<TInput, TOutput> BucketAuto<TInput, TIntermediate, TValue, TOutput>(
  252. this PipelineDefinition<TInput, TIntermediate> pipeline,
  253. Expression<Func<TIntermediate, TValue>> groupBy,
  254. int buckets,
  255. Expression<Func<IGrouping<TValue, TIntermediate>, TOutput>> output,
  256. AggregateBucketAutoOptions options = null,
  257. ExpressionTranslationOptions translationOptions = null)
  258. {
  259. Ensure.IsNotNull(pipeline, nameof(pipeline));
  260. return pipeline.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, output, options, translationOptions));
  261. }
  262. /// <summary>
  263. /// Appends a $count stage to the pipeline.
  264. /// </summary>
  265. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  266. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  267. /// <param name="pipeline">The pipeline.</param>
  268. /// <returns>
  269. /// A new pipeline with an additional stage.
  270. /// </returns>
  271. public static PipelineDefinition<TInput, AggregateCountResult> Count<TInput, TIntermediate>(
  272. this PipelineDefinition<TInput, TIntermediate> pipeline)
  273. {
  274. Ensure.IsNotNull(pipeline, nameof(pipeline));
  275. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Count<TIntermediate>());
  276. }
  277. /// <summary>
  278. /// Appends a $facet stage to the pipeline.
  279. /// </summary>
  280. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  281. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  282. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  283. /// <param name="pipeline">The pipeline.</param>
  284. /// <param name="facets">The facets.</param>
  285. /// <param name="options">The options.</param>
  286. /// <returns>
  287. /// A new pipeline with an additional stage.
  288. /// </returns>
  289. public static PipelineDefinition<TInput, TOutput> Facet<TInput, TIntermediate, TOutput>(
  290. this PipelineDefinition<TInput, TIntermediate> pipeline,
  291. IEnumerable<AggregateFacet<TIntermediate>> facets,
  292. AggregateFacetOptions<TOutput> options = null)
  293. {
  294. Ensure.IsNotNull(pipeline, nameof(pipeline));
  295. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets, options));
  296. }
  297. /// <summary>
  298. /// Appends a $facet stage to the pipeline.
  299. /// </summary>
  300. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  301. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  302. /// <param name="pipeline">The pipeline.</param>
  303. /// <param name="facets">The facets.</param>
  304. /// <returns>
  305. /// The fluent aggregate interface.
  306. /// </returns>
  307. public static PipelineDefinition<TInput, AggregateFacetResults> Facet<TInput, TIntermediate>(
  308. this PipelineDefinition<TInput, TIntermediate> pipeline,
  309. IEnumerable<AggregateFacet<TIntermediate>> facets)
  310. {
  311. Ensure.IsNotNull(pipeline, nameof(pipeline));
  312. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets));
  313. }
  314. /// <summary>
  315. /// Appends a $facet stage to the pipeline.
  316. /// </summary>
  317. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  318. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  319. /// <param name="pipeline">The pipeline.</param>
  320. /// <param name="facets">The facets.</param>
  321. /// <returns>
  322. /// The fluent aggregate interface.
  323. /// </returns>
  324. public static PipelineDefinition<TInput, AggregateFacetResults> Facet<TInput, TIntermediate>(
  325. this PipelineDefinition<TInput, TIntermediate> pipeline,
  326. params AggregateFacet<TIntermediate>[] facets)
  327. {
  328. Ensure.IsNotNull(pipeline, nameof(pipeline));
  329. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets));
  330. }
  331. /// <summary>
  332. /// Appends a $facet stage to the pipeline.
  333. /// </summary>
  334. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  335. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  336. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  337. /// <param name="pipeline">The pipeline.</param>
  338. /// <param name="facets">The facets.</param>
  339. /// <returns>
  340. /// The fluent aggregate interface.
  341. /// </returns>
  342. public static PipelineDefinition<TInput, TOutput> Facet<TInput, TIntermediate, TOutput>(
  343. this PipelineDefinition<TInput, TIntermediate> pipeline,
  344. params AggregateFacet<TIntermediate>[] facets)
  345. {
  346. Ensure.IsNotNull(pipeline, nameof(pipeline));
  347. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet<TIntermediate, TOutput>(facets));
  348. }
  349. /// <summary>
  350. /// Used to start creating a pipeline for {TInput} documents.
  351. /// </summary>
  352. /// <typeparam name="TInput">The type of the output.</typeparam>
  353. /// <param name="inputSerializer">The inputSerializer serializer.</param>
  354. /// <returns>
  355. /// The fluent aggregate interface.
  356. /// </returns>
  357. public static PipelineDefinition<TInput, TInput> For<TInput>(IBsonSerializer<TInput> inputSerializer = null)
  358. {
  359. return new EmptyPipelineDefinition<TInput>(inputSerializer);
  360. }
  361. /// <summary>
  362. /// Appends a $graphLookup stage to the pipeline.
  363. /// </summary>
  364. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  365. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  366. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  367. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  368. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  369. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  370. /// <typeparam name="TAsElement">The type of the as field elements.</typeparam>
  371. /// <typeparam name="TAs">The type of the as field.</typeparam>
  372. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  373. /// <param name="pipeline">The pipeline.</param>
  374. /// <param name="from">The from collection.</param>
  375. /// <param name="connectFromField">The connect from field.</param>
  376. /// <param name="connectToField">The connect to field.</param>
  377. /// <param name="startWith">The start with value.</param>
  378. /// <param name="as">The as field.</param>
  379. /// <param name="depthField">The depth field.</param>
  380. /// <param name="options">The options.</param>
  381. /// <returns>The fluent aggregate interface.</returns>
  382. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAsElement, TAs, TOutput>(
  383. this PipelineDefinition<TInput, TIntermediate> pipeline,
  384. IMongoCollection<TFrom> from,
  385. FieldDefinition<TFrom, TConnectFrom> connectFromField,
  386. FieldDefinition<TFrom, TConnectTo> connectToField,
  387. AggregateExpressionDefinition<TIntermediate, TStartWith> startWith,
  388. FieldDefinition<TOutput, TAs> @as,
  389. FieldDefinition<TAsElement, int> depthField,
  390. AggregateGraphLookupOptions<TFrom, TAsElement, TOutput> options = null)
  391. where TAs : IEnumerable<TAsElement>
  392. {
  393. Ensure.IsNotNull(pipeline, nameof(pipeline));
  394. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField, options));
  395. }
  396. /// <summary>
  397. /// Appends a $graphLookup stage to the pipeline.
  398. /// </summary>
  399. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  400. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  401. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  402. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  403. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  404. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  405. /// <typeparam name="TAs">The type of the as field.</typeparam>
  406. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  407. /// <param name="pipeline">The pipeline.</param>
  408. /// <param name="from">The from collection.</param>
  409. /// <param name="connectFromField">The connect from field.</param>
  410. /// <param name="connectToField">The connect to field.</param>
  411. /// <param name="startWith">The start with value.</param>
  412. /// <param name="as">The as field.</param>
  413. /// <param name="options">The options.</param>
  414. /// <returns>The stage.</returns>
  415. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAs, TOutput>(
  416. this PipelineDefinition<TInput, TIntermediate> pipeline,
  417. IMongoCollection<TFrom> from,
  418. FieldDefinition<TFrom, TConnectFrom> connectFromField,
  419. FieldDefinition<TFrom, TConnectTo> connectToField,
  420. AggregateExpressionDefinition<TIntermediate, TStartWith> startWith,
  421. FieldDefinition<TOutput, TAs> @as,
  422. AggregateGraphLookupOptions<TFrom, TFrom, TOutput> options = null)
  423. where TAs : IEnumerable<TFrom>
  424. {
  425. Ensure.IsNotNull(pipeline, nameof(pipeline));
  426. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, options));
  427. }
  428. /// <summary>
  429. /// Appends a $graphLookup stage to the pipeline.
  430. /// </summary>
  431. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  432. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  433. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  434. /// <param name="pipeline">The pipeline.</param>
  435. /// <param name="from">The from collection.</param>
  436. /// <param name="connectFromField">The connect from field.</param>
  437. /// <param name="connectToField">The connect to field.</param>
  438. /// <param name="startWith">The start with value.</param>
  439. /// <param name="as">The as field.</param>
  440. /// <param name="depthField">The depth field.</param>
  441. /// <returns>The fluent aggregate interface.</returns>
  442. public static PipelineDefinition<TInput, BsonDocument> GraphLookup<TInput, TIntermediate, TFrom>(
  443. this PipelineDefinition<TInput, TIntermediate> pipeline,
  444. IMongoCollection<TFrom> from,
  445. FieldDefinition<TFrom, BsonValue> connectFromField,
  446. FieldDefinition<TFrom, BsonValue> connectToField,
  447. AggregateExpressionDefinition<TIntermediate, BsonValue> startWith,
  448. FieldDefinition<BsonDocument, IEnumerable<BsonDocument>> @as,
  449. FieldDefinition<BsonDocument, int> depthField = null)
  450. {
  451. Ensure.IsNotNull(pipeline, nameof(pipeline));
  452. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField));
  453. }
  454. /// <summary>
  455. /// Appends a $graphLookup stage to the pipeline.
  456. /// </summary>
  457. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  458. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  459. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  460. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  461. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  462. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  463. /// <typeparam name="TAs">The type of the as field.</typeparam>
  464. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  465. /// <param name="pipeline">The pipeline.</param>
  466. /// <param name="from">The from collection.</param>
  467. /// <param name="connectFromField">The connect from field.</param>
  468. /// <param name="connectToField">The connect to field.</param>
  469. /// <param name="startWith">The start with value.</param>
  470. /// <param name="as">The as field.</param>
  471. /// <param name="options">The options.</param>
  472. /// <param name="translationOptions">The translation options.</param>
  473. /// <returns>The stage.</returns>
  474. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAs, TOutput>(
  475. this PipelineDefinition<TInput, TIntermediate> pipeline,
  476. IMongoCollection<TFrom> from,
  477. Expression<Func<TFrom, TConnectFrom>> connectFromField,
  478. Expression<Func<TFrom, TConnectTo>> connectToField,
  479. Expression<Func<TIntermediate, TStartWith>> startWith,
  480. Expression<Func<TOutput, TAs>> @as,
  481. AggregateGraphLookupOptions<TFrom, TFrom, TOutput> options = null,
  482. ExpressionTranslationOptions translationOptions = null)
  483. where TAs : IEnumerable<TFrom>
  484. {
  485. Ensure.IsNotNull(pipeline, nameof(pipeline));
  486. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, options, translationOptions));
  487. }
  488. /// <summary>
  489. /// Appends a $graphLookup stage to the pipeline.
  490. /// </summary>
  491. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  492. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  493. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  494. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  495. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  496. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  497. /// <typeparam name="TAsElement">The type of the as field elements.</typeparam>
  498. /// <typeparam name="TAs">The type of the as field.</typeparam>
  499. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  500. /// <param name="pipeline">The pipeline.</param>
  501. /// <param name="from">The from collection.</param>
  502. /// <param name="connectFromField">The connect from field.</param>
  503. /// <param name="connectToField">The connect to field.</param>
  504. /// <param name="startWith">The start with value.</param>
  505. /// <param name="as">The as field.</param>
  506. /// <param name="depthField">The depth field.</param>
  507. /// <param name="options">The options.</param>
  508. /// <param name="translationOptions">The translation options.</param>
  509. /// <returns>The stage.</returns>
  510. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAsElement, TAs, TOutput>(
  511. this PipelineDefinition<TInput, TIntermediate> pipeline,
  512. IMongoCollection<TFrom> from,
  513. Expression<Func<TFrom, TConnectFrom>> connectFromField,
  514. Expression<Func<TFrom, TConnectTo>> connectToField,
  515. Expression<Func<TIntermediate, TStartWith>> startWith,
  516. Expression<Func<TOutput, TAs>> @as,
  517. Expression<Func<TAsElement, int>> depthField,
  518. AggregateGraphLookupOptions<TFrom, TAsElement, TOutput> options = null,
  519. ExpressionTranslationOptions translationOptions = null)
  520. where TAs : IEnumerable<TAsElement>
  521. {
  522. Ensure.IsNotNull(pipeline, nameof(pipeline));
  523. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField, options, translationOptions));
  524. }
  525. /// <summary>
  526. /// Appends a $group stage to the pipeline.
  527. /// </summary>
  528. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  529. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  530. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  531. /// <param name="pipeline">The pipeline.</param>
  532. /// <param name="group">The group projection.</param>
  533. /// <returns>
  534. /// A new pipeline with an additional stage.
  535. /// </returns>
  536. public static PipelineDefinition<TInput, TOutput> Group<TInput, TIntermediate, TOutput>(
  537. this PipelineDefinition<TInput, TIntermediate> pipeline,
  538. ProjectionDefinition<TIntermediate, TOutput> group)
  539. {
  540. Ensure.IsNotNull(pipeline, nameof(pipeline));
  541. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(group));
  542. }
  543. /// <summary>
  544. /// Appends a group stage to the pipeline.
  545. /// </summary>
  546. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  547. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  548. /// <param name="pipeline">The pipeline.</param>
  549. /// <param name="group">The group projection.</param>
  550. /// <returns>
  551. /// The fluent aggregate interface.
  552. /// </returns>
  553. public static PipelineDefinition<TInput, BsonDocument> Group<TInput, TIntermediate>(
  554. this PipelineDefinition<TInput, TIntermediate> pipeline,
  555. ProjectionDefinition<TIntermediate, BsonDocument> group)
  556. {
  557. Ensure.IsNotNull(pipeline, nameof(pipeline));
  558. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(group));
  559. }
  560. /// <summary>
  561. /// Appends a group stage to the pipeline.
  562. /// </summary>
  563. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  564. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  565. /// <typeparam name="TKey">The type of the key.</typeparam>
  566. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  567. /// <param name="pipeline">The pipeline.</param>
  568. /// <param name="id">The id.</param>
  569. /// <param name="group">The group projection.</param>
  570. /// <param name="translationOptions">The translation options.</param>
  571. /// <returns>
  572. /// The fluent aggregate interface.
  573. /// </returns>
  574. public static PipelineDefinition<TInput, TOutput> Group<TInput, TIntermediate, TKey, TOutput>(
  575. this PipelineDefinition<TInput, TIntermediate> pipeline,
  576. Expression<Func<TIntermediate, TKey>> id,
  577. Expression<Func<IGrouping<TKey, TIntermediate>, TOutput>> group,
  578. ExpressionTranslationOptions translationOptions = null)
  579. {
  580. Ensure.IsNotNull(pipeline, nameof(pipeline));
  581. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(id, group, translationOptions));
  582. }
  583. /// <summary>
  584. /// Appends a $limit stage to the pipeline.
  585. /// </summary>
  586. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  587. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  588. /// <param name="pipeline">The pipeline.</param>
  589. /// <param name="limit">The limit.</param>
  590. /// <returns>
  591. /// A new pipeline with an additional stage.
  592. /// </returns>
  593. public static PipelineDefinition<TInput, TOutput> Limit<TInput, TOutput>(
  594. this PipelineDefinition<TInput, TOutput> pipeline,
  595. int limit)
  596. {
  597. Ensure.IsNotNull(pipeline, nameof(pipeline));
  598. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Limit<TOutput>(limit));
  599. }
  600. /// <summary>
  601. /// Appends a $lookup stage to the pipeline.
  602. /// </summary>
  603. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  604. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  605. /// <typeparam name="TForeignDocument">The type of the foreign collection documents.</typeparam>
  606. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  607. /// <param name="pipeline">The pipeline.</param>
  608. /// <param name="foreignCollection">The foreign collection.</param>
  609. /// <param name="localField">The local field.</param>
  610. /// <param name="foreignField">The foreign field.</param>
  611. /// <param name="as">The "as" field.</param>
  612. /// <param name="options">The options.</param>
  613. /// <returns>
  614. /// A new pipeline with an additional stage.
  615. /// </returns>
  616. public static PipelineDefinition<TInput, TOutput> Lookup<TInput, TIntermediate, TForeignDocument, TOutput>(
  617. this PipelineDefinition<TInput, TIntermediate> pipeline,
  618. IMongoCollection<TForeignDocument> foreignCollection,
  619. FieldDefinition<TIntermediate> localField,
  620. FieldDefinition<TForeignDocument> foreignField,
  621. FieldDefinition<TOutput> @as,
  622. AggregateLookupOptions<TForeignDocument, TOutput> options = null)
  623. {
  624. Ensure.IsNotNull(pipeline, nameof(pipeline));
  625. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup(foreignCollection, localField, foreignField, @as, options));
  626. }
  627. /// <summary>
  628. /// Appends a lookup stage to the pipeline.
  629. /// </summary>
  630. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  631. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  632. /// <typeparam name="TForeignDocument">The type of the foreign collection documents.</typeparam>
  633. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  634. /// <param name="pipeline">The pipeline.</param>
  635. /// <param name="foreignCollection">The foreign collection.</param>
  636. /// <param name="localField">The local field.</param>
  637. /// <param name="foreignField">The foreign field.</param>
  638. /// <param name="as">The "as" field.</param>
  639. /// <param name="options">The options.</param>
  640. /// <returns>
  641. /// The fluent aggregate interface.
  642. /// </returns>
  643. public static PipelineDefinition<TInput, TOutput> Lookup<TInput, TIntermediate, TForeignDocument, TOutput>(
  644. this PipelineDefinition<TInput, TIntermediate> pipeline,
  645. IMongoCollection<TForeignDocument> foreignCollection,
  646. Expression<Func<TIntermediate, object>> localField,
  647. Expression<Func<TForeignDocument, object>> foreignField,
  648. Expression<Func<TOutput, object>> @as,
  649. AggregateLookupOptions<TForeignDocument, TOutput> options = null)
  650. {
  651. Ensure.IsNotNull(pipeline, nameof(pipeline));
  652. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup(foreignCollection, localField, foreignField, @as, options));
  653. }
  654. /// <summary>
  655. /// Appends a $match stage to the pipeline.
  656. /// </summary>
  657. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  658. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  659. /// <param name="pipeline">The pipeline.</param>
  660. /// <param name="filter">The filter.</param>
  661. /// <returns>
  662. /// A new pipeline with an additional stage.
  663. /// </returns>
  664. public static PipelineDefinition<TInput, TOutput> Match<TInput, TOutput>(
  665. this PipelineDefinition<TInput, TOutput> pipeline,
  666. FilterDefinition<TOutput> filter)
  667. {
  668. Ensure.IsNotNull(pipeline, nameof(pipeline));
  669. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Match(filter));
  670. }
  671. /// <summary>
  672. /// Appends a match stage to the pipeline.
  673. /// </summary>
  674. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  675. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  676. /// <param name="pipeline">The pipeline.</param>
  677. /// <param name="filter">The filter.</param>
  678. /// <returns>
  679. /// The fluent aggregate interface.
  680. /// </returns>
  681. public static PipelineDefinition<TInput, TOutput> Match<TInput, TOutput>(
  682. this PipelineDefinition<TInput, TOutput> pipeline,
  683. Expression<Func<TOutput, bool>> filter)
  684. {
  685. Ensure.IsNotNull(pipeline, nameof(pipeline));
  686. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Match(filter));
  687. }
  688. /// <summary>
  689. /// Appends a $match stage to the pipeline to select documents of a certain type.
  690. /// </summary>
  691. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  692. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  693. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  694. /// <param name="pipeline">The pipeline.</param>
  695. /// <param name="outputSerializer">The output serializer.</param>
  696. /// <returns>
  697. /// A new pipeline with an additional stage.
  698. /// </returns>
  699. /// <exception cref="System.NotSupportedException"></exception>
  700. public static PipelineDefinition<TInput, TOutput> OfType<TInput, TIntermediate, TOutput>(
  701. this PipelineDefinition<TInput, TIntermediate> pipeline,
  702. IBsonSerializer<TOutput> outputSerializer = null)
  703. where TOutput : TIntermediate
  704. {
  705. Ensure.IsNotNull(pipeline, nameof(pipeline));
  706. return pipeline.AppendStage(PipelineStageDefinitionBuilder.OfType<TIntermediate, TOutput>(outputSerializer));
  707. }
  708. /// <summary>
  709. /// Appends a $out stage to the pipeline.
  710. /// </summary>
  711. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  712. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  713. /// <param name="pipeline">The pipeline.</param>
  714. /// <param name="outputCollection">The output collection.</param>
  715. /// <returns>
  716. /// A new pipeline with an additional stage.
  717. /// </returns>
  718. /// <exception cref="System.NotSupportedException"></exception>
  719. public static PipelineDefinition<TInput, TOutput> Out<TInput, TOutput>(
  720. this PipelineDefinition<TInput, TOutput> pipeline,
  721. IMongoCollection<TOutput> outputCollection)
  722. {
  723. Ensure.IsNotNull(pipeline, nameof(pipeline));
  724. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Out<TOutput>(outputCollection));
  725. }
  726. /// <summary>
  727. /// Appends a $project stage to the pipeline.
  728. /// </summary>
  729. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  730. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  731. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  732. /// <param name="pipeline">The pipeline.</param>
  733. /// <param name="projection">The projection.</param>
  734. /// <returns>
  735. /// A new pipeline with an additional stage.
  736. /// </returns>
  737. /// <exception cref="System.NotSupportedException"></exception>
  738. public static PipelineDefinition<TInput, TOutput> Project<TInput, TIntermediate, TOutput>(
  739. this PipelineDefinition<TInput, TIntermediate> pipeline,
  740. ProjectionDefinition<TIntermediate, TOutput> projection)
  741. {
  742. Ensure.IsNotNull(pipeline, nameof(pipeline));
  743. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection));
  744. }
  745. /// <summary>
  746. /// Appends a project stage to the pipeline.
  747. /// </summary>
  748. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  749. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  750. /// <param name="pipeline">The pipeline.</param>
  751. /// <param name="projection">The projection.</param>
  752. /// <returns>
  753. /// The fluent aggregate interface.
  754. /// </returns>
  755. public static PipelineDefinition<TInput, BsonDocument> Project<TInput, TIntermediate>(
  756. this PipelineDefinition<TInput, TIntermediate> pipeline,
  757. ProjectionDefinition<TIntermediate, BsonDocument> projection)
  758. {
  759. Ensure.IsNotNull(pipeline, nameof(pipeline));
  760. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection));
  761. }
  762. /// <summary>
  763. /// Appends a project stage to the pipeline.
  764. /// </summary>
  765. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  766. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  767. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  768. /// <param name="pipeline">The pipeline.</param>
  769. /// <param name="projection">The projection.</param>
  770. /// <param name="translationOptions">The translation options.</param>
  771. /// <returns>
  772. /// The fluent aggregate interface.
  773. /// </returns>
  774. public static PipelineDefinition<TInput, TOutput> Project<TInput, TIntermediate, TOutput>(
  775. this PipelineDefinition<TInput, TIntermediate> pipeline,
  776. Expression<Func<TIntermediate, TOutput>> projection,
  777. ExpressionTranslationOptions translationOptions = null)
  778. {
  779. Ensure.IsNotNull(pipeline, nameof(pipeline));
  780. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection, translationOptions));
  781. }
  782. /// <summary>
  783. /// Appends a $replaceRoot stage to the pipeline.
  784. /// </summary>
  785. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  786. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  787. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  788. /// <param name="pipeline">The pipeline.</param>
  789. /// <param name="newRoot">The new root.</param>
  790. /// <returns>
  791. /// A new pipeline with an additional stage.
  792. /// </returns>
  793. public static PipelineDefinition<TInput, TOutput> ReplaceRoot<TInput, TIntermediate, TOutput>(
  794. this PipelineDefinition<TInput, TIntermediate> pipeline,
  795. AggregateExpressionDefinition<TIntermediate, TOutput> newRoot)
  796. {
  797. Ensure.IsNotNull(pipeline, nameof(pipeline));
  798. return pipeline.AppendStage(PipelineStageDefinitionBuilder.ReplaceRoot(newRoot));
  799. }
  800. /// <summary>
  801. /// Appends a $replaceRoot stage to the pipeline.
  802. /// </summary>
  803. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  804. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  805. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  806. /// <param name="pipeline">The pipeline.</param>
  807. /// <param name="newRoot">The new root.</param>
  808. /// <param name="translationOptions">The translation options.</param>
  809. /// <returns>
  810. /// The fluent aggregate interface.
  811. /// </returns>
  812. public static PipelineDefinition<TInput, TOutput> ReplaceRoot<TInput, TIntermediate, TOutput>(
  813. this PipelineDefinition<TInput, TIntermediate> pipeline,
  814. Expression<Func<TIntermediate, TOutput>> newRoot,
  815. ExpressionTranslationOptions translationOptions = null)
  816. {
  817. Ensure.IsNotNull(pipeline, nameof(pipeline));
  818. return pipeline.AppendStage(PipelineStageDefinitionBuilder.ReplaceRoot(newRoot, translationOptions));
  819. }
  820. /// <summary>
  821. /// Appends a $skip stage to the pipeline.
  822. /// </summary>
  823. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  824. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  825. /// <param name="pipeline">The pipeline.</param>
  826. /// <param name="skip">The number of documents to skip.</param>
  827. /// <returns>
  828. /// A new pipeline with an additional stage.
  829. /// </returns>
  830. public static PipelineDefinition<TInput, TOutput> Skip<TInput, TOutput>(
  831. this PipelineDefinition<TInput, TOutput> pipeline,
  832. int skip)
  833. {
  834. Ensure.IsNotNull(pipeline, nameof(pipeline));
  835. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Skip<TOutput>(skip));
  836. }
  837. /// <summary>
  838. /// Appends a $sort stage to the pipeline.
  839. /// </summary>
  840. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  841. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  842. /// <param name="pipeline">The pipeline.</param>
  843. /// <param name="sort">The sort definition.</param>
  844. /// <returns>
  845. /// A new pipeline with an additional stage.
  846. /// </returns>
  847. public static PipelineDefinition<TInput, TOutput> Sort<TInput, TOutput>(
  848. this PipelineDefinition<TInput, TOutput> pipeline,
  849. SortDefinition<TOutput> sort)
  850. {
  851. Ensure.IsNotNull(pipeline, nameof(pipeline));
  852. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Sort(sort));
  853. }
  854. /// <summary>
  855. /// Appends a $sortByCount stage to the pipeline.
  856. /// </summary>
  857. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  858. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  859. /// <typeparam name="TValue">The type of the values.</typeparam>
  860. /// <param name="pipeline">The pipeline.</param>
  861. /// <param name="value">The value expression.</param>
  862. /// <returns>
  863. /// A new pipeline with an additional stage.
  864. /// </returns>
  865. public static PipelineDefinition<TInput, AggregateSortByCountResult<TValue>> SortByCount<TInput, TIntermediate, TValue>(
  866. this PipelineDefinition<TInput, TIntermediate> pipeline,
  867. AggregateExpressionDefinition<TIntermediate, TValue> value)
  868. {
  869. Ensure.IsNotNull(pipeline, nameof(pipeline));
  870. return pipeline.AppendStage(PipelineStageDefinitionBuilder.SortByCount(value));
  871. }
  872. /// <summary>
  873. /// Appends a sortByCount stage to the pipeline.
  874. /// </summary>
  875. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  876. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  877. /// <typeparam name="TValue">The type of the values.</typeparam>
  878. /// <param name="pipeline">The pipeline.</param>
  879. /// <param name="value">The value expression.</param>
  880. /// <param name="translationOptions">The translation options.</param>
  881. /// <returns>
  882. /// The fluent aggregate interface.
  883. /// </returns>
  884. public static PipelineDefinition<TInput, AggregateSortByCountResult<TValue>> SortByCount<TInput, TIntermediate, TValue>(
  885. this PipelineDefinition<TInput, TIntermediate> pipeline,
  886. Expression<Func<TIntermediate, TValue>> value,
  887. ExpressionTranslationOptions translationOptions = null)
  888. {
  889. Ensure.IsNotNull(pipeline, nameof(pipeline));
  890. return pipeline.AppendStage(PipelineStageDefinitionBuilder.SortByCount(value, translationOptions));
  891. }
  892. /// <summary>
  893. /// Appends an $unwind stage to the pipeline.
  894. /// </summary>
  895. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  896. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  897. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  898. /// <param name="pipeline">The pipeline.</param>
  899. /// <param name="field">The field.</param>
  900. /// <param name="options">The options.</param>
  901. /// <returns>
  902. /// A new pipeline with an additional stage.
  903. /// </returns>
  904. public static PipelineDefinition<TInput, TOutput> Unwind<TInput, TIntermediate, TOutput>(
  905. this PipelineDefinition<TInput, TIntermediate> pipeline,
  906. FieldDefinition<TIntermediate> field,
  907. AggregateUnwindOptions<TOutput> options = null)
  908. {
  909. Ensure.IsNotNull(pipeline, nameof(pipeline));
  910. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  911. }
  912. /// <summary>
  913. /// Appends an unwind stage to the pipeline.
  914. /// </summary>
  915. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  916. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  917. /// <param name="pipeline">The pipeline.</param>
  918. /// <param name="field">The field to unwind.</param>
  919. /// <param name="options">The options.</param>
  920. /// <returns>
  921. /// The fluent aggregate interface.
  922. /// </returns>
  923. public static PipelineDefinition<TInput, BsonDocument> Unwind<TInput, TIntermediate>(
  924. this PipelineDefinition<TInput, TIntermediate> pipeline,
  925. FieldDefinition<TIntermediate> field,
  926. AggregateUnwindOptions<BsonDocument> options = null)
  927. {
  928. Ensure.IsNotNull(pipeline, nameof(pipeline));
  929. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  930. }
  931. /// <summary>
  932. /// Appends an unwind stage to the pipeline.
  933. /// </summary>
  934. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  935. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  936. /// <param name="pipeline">The pipeline.</param>
  937. /// <param name="field">The field to unwind.</param>
  938. /// <param name="options">The options.</param>
  939. /// <returns>
  940. /// The fluent aggregate interface.
  941. /// </returns>
  942. public static PipelineDefinition<TInput, BsonDocument> Unwind<TInput, TIntermediate>(
  943. this PipelineDefinition<TInput, TIntermediate> pipeline,
  944. Expression<Func<TIntermediate, object>> field,
  945. AggregateUnwindOptions<BsonDocument> options = null)
  946. {
  947. Ensure.IsNotNull(pipeline, nameof(pipeline));
  948. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  949. }
  950. /// <summary>
  951. /// Appends an unwind stage to the pipeline.
  952. /// </summary>
  953. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  954. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  955. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  956. /// <param name="pipeline">The pipeline.</param>
  957. /// <param name="field">The field to unwind.</param>
  958. /// <param name="options">The options.</param>
  959. /// <returns>
  960. /// The fluent aggregate interface.
  961. /// </returns>
  962. public static PipelineDefinition<TInput, TOutput> Unwind<TInput, TIntermediate, TOutput>(
  963. this PipelineDefinition<TInput, TIntermediate> pipeline,
  964. Expression<Func<TIntermediate, object>> field,
  965. AggregateUnwindOptions<TOutput> options = null)
  966. {
  967. Ensure.IsNotNull(pipeline, nameof(pipeline));
  968. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  969. }
  970. }
  971. /// <summary>
  972. /// Represents a pipeline consisting of an existing pipeline with one additional stage appended.
  973. /// </summary>
  974. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  975. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  976. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  977. public sealed class AppendedStagePipelineDefinition<TInput, TIntermediate, TOutput> : PipelineDefinition<TInput, TOutput>
  978. {
  979. private readonly IBsonSerializer<TOutput> _outputSerializer;
  980. private readonly PipelineDefinition<TInput, TIntermediate> _pipeline;
  981. private readonly PipelineStageDefinition<TIntermediate, TOutput> _stage;
  982. /// <summary>
  983. /// Initializes a new instance of the <see cref="AppendedStagePipelineDefinition{TInput, TIntermediate, TOutput}" /> class.
  984. /// </summary>
  985. /// <param name="pipeline">The pipeline.</param>
  986. /// <param name="stage">The stage.</param>
  987. /// <param name="outputSerializer">The output serializer.</param>
  988. public AppendedStagePipelineDefinition(
  989. PipelineDefinition<TInput, TIntermediate> pipeline,
  990. PipelineStageDefinition<TIntermediate, TOutput> stage,
  991. IBsonSerializer<TOutput> outputSerializer = null)
  992. {
  993. _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline));
  994. _stage = Ensure.IsNotNull(stage, nameof(stage));
  995. _outputSerializer = outputSerializer; // can be null
  996. }
  997. /// <inheritdoc/>
  998. public override IBsonSerializer<TOutput> OutputSerializer => _outputSerializer;
  999. /// <inheritdoc/>
  1000. public override IEnumerable<IPipelineStageDefinition> Stages => _pipeline.Stages.Concat(new[] { _stage });
  1001. /// <inheritdoc/>
  1002. public override RenderedPipelineDefinition<TOutput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1003. {
  1004. var renderedPipeline = _pipeline.Render(inputSerializer, serializerRegistry);
  1005. var renderedStage = _stage.Render(renderedPipeline.OutputSerializer, serializerRegistry);
  1006. var documents = renderedPipeline.Documents.Concat(new[] { renderedStage.Document });
  1007. var outputSerializer = _outputSerializer ?? renderedStage.OutputSerializer;
  1008. return new RenderedPipelineDefinition<TOutput>(documents, outputSerializer);
  1009. }
  1010. }
  1011. /// <summary>
  1012. /// Represents an empty pipeline.
  1013. /// </summary>
  1014. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1015. public sealed class EmptyPipelineDefinition<TInput> : PipelineDefinition<TInput, TInput>
  1016. {
  1017. private readonly IBsonSerializer<TInput> _inputSerializer;
  1018. /// <summary>
  1019. /// Initializes a new instance of the <see cref="EmptyPipelineDefinition{TOutput}"/> class.
  1020. /// </summary>
  1021. /// <param name="inputSerializer">The output serializer.</param>
  1022. public EmptyPipelineDefinition(IBsonSerializer<TInput> inputSerializer = null)
  1023. {
  1024. _inputSerializer = inputSerializer; // can be null
  1025. }
  1026. /// <inheritdoc/>
  1027. public override IBsonSerializer<TInput> OutputSerializer => _inputSerializer;
  1028. /// <inheritdoc/>
  1029. public override IEnumerable<IPipelineStageDefinition> Stages => Enumerable.Empty<IPipelineStageDefinition>();
  1030. /// <inheritdoc/>
  1031. public override RenderedPipelineDefinition<TInput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1032. {
  1033. var documents = Enumerable.Empty<BsonDocument>();
  1034. return new RenderedPipelineDefinition<TInput>(documents, _inputSerializer ?? inputSerializer);
  1035. }
  1036. }
  1037. /// <summary>
  1038. /// Represents a pipeline consisting of an existing pipeline with one additional stage prepended.
  1039. /// </summary>
  1040. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1041. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1042. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  1043. public sealed class PrependedStagePipelineDefinition<TInput, TIntermediate, TOutput> : PipelineDefinition<TInput, TOutput>
  1044. {
  1045. private readonly IBsonSerializer<TOutput> _outputSerializer;
  1046. private readonly PipelineDefinition<TIntermediate, TOutput> _pipeline;
  1047. private readonly PipelineStageDefinition<TInput, TIntermediate> _stage;
  1048. /// <summary>
  1049. /// Initializes a new instance of the <see cref="PrependedStagePipelineDefinition{TInput, TIntermediate, TOutput}" /> class.
  1050. /// </summary>
  1051. /// <param name="stage">The stage.</param>
  1052. /// <param name="pipeline">The pipeline.</param>
  1053. /// <param name="outputSerializer">The output serializer.</param>
  1054. public PrependedStagePipelineDefinition(
  1055. PipelineStageDefinition<TInput, TIntermediate> stage,
  1056. PipelineDefinition<TIntermediate, TOutput> pipeline,
  1057. IBsonSerializer<TOutput> outputSerializer = null)
  1058. {
  1059. _stage = Ensure.IsNotNull(stage, nameof(stage));
  1060. _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline));
  1061. _outputSerializer = outputSerializer; // can be null
  1062. }
  1063. /// <inheritdoc/>
  1064. public override IBsonSerializer<TOutput> OutputSerializer => _outputSerializer;
  1065. /// <inheritdoc/>
  1066. public override IEnumerable<IPipelineStageDefinition> Stages => new[] { _stage }.Concat(_pipeline.Stages);
  1067. /// <inheritdoc/>
  1068. public override RenderedPipelineDefinition<TOutput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1069. {
  1070. var renderedStage = _stage.Render(inputSerializer, serializerRegistry);
  1071. var renderedPipeline = _pipeline.Render(renderedStage.OutputSerializer, serializerRegistry);
  1072. var documents = new[] { renderedStage.Document }.Concat(renderedPipeline.Documents);
  1073. var outputSerializer = _outputSerializer ?? renderedPipeline.OutputSerializer;
  1074. return new RenderedPipelineDefinition<TOutput>(documents, outputSerializer);
  1075. }
  1076. }
  1077. /// <summary>
  1078. /// Represents a pipeline with the output serializer replaced.
  1079. /// </summary>
  1080. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1081. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1082. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  1083. /// <seealso cref="MongoDB.Driver.PipelineDefinition{TInput, TOutput}" />
  1084. public sealed class ReplaceOutputSerializerPipelineDefinition<TInput, TIntermediate, TOutput> : PipelineDefinition<TInput, TOutput>
  1085. {
  1086. private readonly IBsonSerializer<TOutput> _outputSerializer;
  1087. private readonly PipelineDefinition<TInput, TIntermediate> _pipeline;
  1088. /// <summary>
  1089. /// Initializes a new instance of the <see cref="ReplaceOutputSerializerPipelineDefinition{TInput, TIntermediate, TOutput}"/> class.
  1090. /// </summary>
  1091. /// <param name="pipeline">The pipeline.</param>
  1092. /// <param name="outputSerializer">The output serializer.</param>
  1093. public ReplaceOutputSerializerPipelineDefinition(
  1094. PipelineDefinition<TInput, TIntermediate> pipeline,
  1095. IBsonSerializer<TOutput> outputSerializer = null)
  1096. {
  1097. _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline));
  1098. _outputSerializer = outputSerializer; // can be null
  1099. }
  1100. /// <inheritdoc/>
  1101. public override IBsonSerializer<TOutput> OutputSerializer => _outputSerializer;
  1102. /// <inheritdoc/>
  1103. public override IEnumerable<IPipelineStageDefinition> Stages => _pipeline.Stages;
  1104. /// <inheritdoc/>
  1105. public override RenderedPipelineDefinition<TOutput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1106. {
  1107. var renderedPipeline = _pipeline.Render(inputSerializer, serializerRegistry);
  1108. var outputSerializer = _outputSerializer ?? serializerRegistry.GetSerializer<TOutput>();
  1109. return new RenderedPipelineDefinition<TOutput>(renderedPipeline.Documents, outputSerializer);
  1110. }
  1111. }
  1112. }