PipelineDefinitionBuilder.cs 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. /* Copyright 2016-present 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 $changeStream stage to the pipeline.
  264. /// Normally you would prefer to use the Watch method of <see cref="IMongoCollection{TDocument}" />.
  265. /// Only use this method if subsequent stages project away the resume token (the _id)
  266. /// or you don't want the resulting cursor to automatically resume.
  267. /// </summary>
  268. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  269. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  270. /// <param name="pipeline">The pipeline.</param>
  271. /// <param name="options">The options.</param>
  272. /// <returns>
  273. /// The fluent aggregate interface.
  274. /// </returns>
  275. public static PipelineDefinition<TInput, ChangeStreamDocument<TIntermediate>> ChangeStream<TInput, TIntermediate>(
  276. this PipelineDefinition<TInput, TIntermediate> pipeline,
  277. ChangeStreamStageOptions options = null)
  278. {
  279. Ensure.IsNotNull(pipeline, nameof(pipeline));
  280. return pipeline.AppendStage(PipelineStageDefinitionBuilder.ChangeStream<TIntermediate>(options));
  281. }
  282. /// <summary>
  283. /// Appends a $count stage to the pipeline.
  284. /// </summary>
  285. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  286. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  287. /// <param name="pipeline">The pipeline.</param>
  288. /// <returns>
  289. /// A new pipeline with an additional stage.
  290. /// </returns>
  291. public static PipelineDefinition<TInput, AggregateCountResult> Count<TInput, TIntermediate>(
  292. this PipelineDefinition<TInput, TIntermediate> pipeline)
  293. {
  294. Ensure.IsNotNull(pipeline, nameof(pipeline));
  295. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Count<TIntermediate>());
  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. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  303. /// <param name="pipeline">The pipeline.</param>
  304. /// <param name="facets">The facets.</param>
  305. /// <param name="options">The options.</param>
  306. /// <returns>
  307. /// A new pipeline with an additional stage.
  308. /// </returns>
  309. public static PipelineDefinition<TInput, TOutput> Facet<TInput, TIntermediate, TOutput>(
  310. this PipelineDefinition<TInput, TIntermediate> pipeline,
  311. IEnumerable<AggregateFacet<TIntermediate>> facets,
  312. AggregateFacetOptions<TOutput> options = null)
  313. {
  314. Ensure.IsNotNull(pipeline, nameof(pipeline));
  315. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets, options));
  316. }
  317. /// <summary>
  318. /// Appends a $facet stage to the pipeline.
  319. /// </summary>
  320. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  321. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  322. /// <param name="pipeline">The pipeline.</param>
  323. /// <param name="facets">The facets.</param>
  324. /// <returns>
  325. /// The fluent aggregate interface.
  326. /// </returns>
  327. public static PipelineDefinition<TInput, AggregateFacetResults> Facet<TInput, TIntermediate>(
  328. this PipelineDefinition<TInput, TIntermediate> pipeline,
  329. IEnumerable<AggregateFacet<TIntermediate>> facets)
  330. {
  331. Ensure.IsNotNull(pipeline, nameof(pipeline));
  332. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets));
  333. }
  334. /// <summary>
  335. /// Appends a $facet stage to the pipeline.
  336. /// </summary>
  337. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  338. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  339. /// <param name="pipeline">The pipeline.</param>
  340. /// <param name="facets">The facets.</param>
  341. /// <returns>
  342. /// The fluent aggregate interface.
  343. /// </returns>
  344. public static PipelineDefinition<TInput, AggregateFacetResults> Facet<TInput, TIntermediate>(
  345. this PipelineDefinition<TInput, TIntermediate> pipeline,
  346. params AggregateFacet<TIntermediate>[] facets)
  347. {
  348. Ensure.IsNotNull(pipeline, nameof(pipeline));
  349. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet(facets));
  350. }
  351. /// <summary>
  352. /// Appends a $facet stage to the pipeline.
  353. /// </summary>
  354. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  355. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  356. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  357. /// <param name="pipeline">The pipeline.</param>
  358. /// <param name="facets">The facets.</param>
  359. /// <returns>
  360. /// The fluent aggregate interface.
  361. /// </returns>
  362. public static PipelineDefinition<TInput, TOutput> Facet<TInput, TIntermediate, TOutput>(
  363. this PipelineDefinition<TInput, TIntermediate> pipeline,
  364. params AggregateFacet<TIntermediate>[] facets)
  365. {
  366. Ensure.IsNotNull(pipeline, nameof(pipeline));
  367. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Facet<TIntermediate, TOutput>(facets));
  368. }
  369. /// <summary>
  370. /// Used to start creating a pipeline for {TInput} documents.
  371. /// </summary>
  372. /// <typeparam name="TInput">The type of the output.</typeparam>
  373. /// <param name="inputSerializer">The inputSerializer serializer.</param>
  374. /// <returns>
  375. /// The fluent aggregate interface.
  376. /// </returns>
  377. public static PipelineDefinition<TInput, TInput> For<TInput>(IBsonSerializer<TInput> inputSerializer = null)
  378. {
  379. return new EmptyPipelineDefinition<TInput>(inputSerializer);
  380. }
  381. /// <summary>
  382. /// Appends a $graphLookup stage to the pipeline.
  383. /// </summary>
  384. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  385. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  386. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  387. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  388. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  389. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  390. /// <typeparam name="TAsElement">The type of the as field elements.</typeparam>
  391. /// <typeparam name="TAs">The type of the as field.</typeparam>
  392. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  393. /// <param name="pipeline">The pipeline.</param>
  394. /// <param name="from">The from collection.</param>
  395. /// <param name="connectFromField">The connect from field.</param>
  396. /// <param name="connectToField">The connect to field.</param>
  397. /// <param name="startWith">The start with value.</param>
  398. /// <param name="as">The as field.</param>
  399. /// <param name="depthField">The depth field.</param>
  400. /// <param name="options">The options.</param>
  401. /// <returns>The fluent aggregate interface.</returns>
  402. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAsElement, TAs, TOutput>(
  403. this PipelineDefinition<TInput, TIntermediate> pipeline,
  404. IMongoCollection<TFrom> from,
  405. FieldDefinition<TFrom, TConnectFrom> connectFromField,
  406. FieldDefinition<TFrom, TConnectTo> connectToField,
  407. AggregateExpressionDefinition<TIntermediate, TStartWith> startWith,
  408. FieldDefinition<TOutput, TAs> @as,
  409. FieldDefinition<TAsElement, int> depthField,
  410. AggregateGraphLookupOptions<TFrom, TAsElement, TOutput> options = null)
  411. where TAs : IEnumerable<TAsElement>
  412. {
  413. Ensure.IsNotNull(pipeline, nameof(pipeline));
  414. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField, options));
  415. }
  416. /// <summary>
  417. /// Appends a $graphLookup stage to the pipeline.
  418. /// </summary>
  419. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  420. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  421. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  422. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  423. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  424. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  425. /// <typeparam name="TAs">The type of the as field.</typeparam>
  426. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  427. /// <param name="pipeline">The pipeline.</param>
  428. /// <param name="from">The from collection.</param>
  429. /// <param name="connectFromField">The connect from field.</param>
  430. /// <param name="connectToField">The connect to field.</param>
  431. /// <param name="startWith">The start with value.</param>
  432. /// <param name="as">The as field.</param>
  433. /// <param name="options">The options.</param>
  434. /// <returns>The stage.</returns>
  435. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAs, TOutput>(
  436. this PipelineDefinition<TInput, TIntermediate> pipeline,
  437. IMongoCollection<TFrom> from,
  438. FieldDefinition<TFrom, TConnectFrom> connectFromField,
  439. FieldDefinition<TFrom, TConnectTo> connectToField,
  440. AggregateExpressionDefinition<TIntermediate, TStartWith> startWith,
  441. FieldDefinition<TOutput, TAs> @as,
  442. AggregateGraphLookupOptions<TFrom, TFrom, TOutput> options = null)
  443. where TAs : IEnumerable<TFrom>
  444. {
  445. Ensure.IsNotNull(pipeline, nameof(pipeline));
  446. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, options));
  447. }
  448. /// <summary>
  449. /// Appends a $graphLookup stage to the pipeline.
  450. /// </summary>
  451. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  452. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  453. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  454. /// <param name="pipeline">The pipeline.</param>
  455. /// <param name="from">The from collection.</param>
  456. /// <param name="connectFromField">The connect from field.</param>
  457. /// <param name="connectToField">The connect to field.</param>
  458. /// <param name="startWith">The start with value.</param>
  459. /// <param name="as">The as field.</param>
  460. /// <param name="depthField">The depth field.</param>
  461. /// <returns>The fluent aggregate interface.</returns>
  462. public static PipelineDefinition<TInput, BsonDocument> GraphLookup<TInput, TIntermediate, TFrom>(
  463. this PipelineDefinition<TInput, TIntermediate> pipeline,
  464. IMongoCollection<TFrom> from,
  465. FieldDefinition<TFrom, BsonValue> connectFromField,
  466. FieldDefinition<TFrom, BsonValue> connectToField,
  467. AggregateExpressionDefinition<TIntermediate, BsonValue> startWith,
  468. FieldDefinition<BsonDocument, IEnumerable<BsonDocument>> @as,
  469. FieldDefinition<BsonDocument, int> depthField = null)
  470. {
  471. Ensure.IsNotNull(pipeline, nameof(pipeline));
  472. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField));
  473. }
  474. /// <summary>
  475. /// Appends a $graphLookup stage to the pipeline.
  476. /// </summary>
  477. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  478. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  479. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  480. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  481. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  482. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  483. /// <typeparam name="TAs">The type of the as field.</typeparam>
  484. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  485. /// <param name="pipeline">The pipeline.</param>
  486. /// <param name="from">The from collection.</param>
  487. /// <param name="connectFromField">The connect from field.</param>
  488. /// <param name="connectToField">The connect to field.</param>
  489. /// <param name="startWith">The start with value.</param>
  490. /// <param name="as">The as field.</param>
  491. /// <param name="options">The options.</param>
  492. /// <param name="translationOptions">The translation options.</param>
  493. /// <returns>The stage.</returns>
  494. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAs, TOutput>(
  495. this PipelineDefinition<TInput, TIntermediate> pipeline,
  496. IMongoCollection<TFrom> from,
  497. Expression<Func<TFrom, TConnectFrom>> connectFromField,
  498. Expression<Func<TFrom, TConnectTo>> connectToField,
  499. Expression<Func<TIntermediate, TStartWith>> startWith,
  500. Expression<Func<TOutput, TAs>> @as,
  501. AggregateGraphLookupOptions<TFrom, TFrom, TOutput> options = null,
  502. ExpressionTranslationOptions translationOptions = null)
  503. where TAs : IEnumerable<TFrom>
  504. {
  505. Ensure.IsNotNull(pipeline, nameof(pipeline));
  506. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, options, translationOptions));
  507. }
  508. /// <summary>
  509. /// Appends a $graphLookup stage to the pipeline.
  510. /// </summary>
  511. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  512. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  513. /// <typeparam name="TFrom">The type of the from documents.</typeparam>
  514. /// <typeparam name="TConnectFrom">The type of the connect from field (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  515. /// <typeparam name="TConnectTo">The type of the connect to field.</typeparam>
  516. /// <typeparam name="TStartWith">The type of the start with expression (must be either TConnectTo or a type that implements IEnumerable{TConnectTo}).</typeparam>
  517. /// <typeparam name="TAsElement">The type of the as field elements.</typeparam>
  518. /// <typeparam name="TAs">The type of the as field.</typeparam>
  519. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  520. /// <param name="pipeline">The pipeline.</param>
  521. /// <param name="from">The from collection.</param>
  522. /// <param name="connectFromField">The connect from field.</param>
  523. /// <param name="connectToField">The connect to field.</param>
  524. /// <param name="startWith">The start with value.</param>
  525. /// <param name="as">The as field.</param>
  526. /// <param name="depthField">The depth field.</param>
  527. /// <param name="options">The options.</param>
  528. /// <param name="translationOptions">The translation options.</param>
  529. /// <returns>The stage.</returns>
  530. public static PipelineDefinition<TInput, TOutput> GraphLookup<TInput, TIntermediate, TFrom, TConnectFrom, TConnectTo, TStartWith, TAsElement, TAs, TOutput>(
  531. this PipelineDefinition<TInput, TIntermediate> pipeline,
  532. IMongoCollection<TFrom> from,
  533. Expression<Func<TFrom, TConnectFrom>> connectFromField,
  534. Expression<Func<TFrom, TConnectTo>> connectToField,
  535. Expression<Func<TIntermediate, TStartWith>> startWith,
  536. Expression<Func<TOutput, TAs>> @as,
  537. Expression<Func<TAsElement, int>> depthField,
  538. AggregateGraphLookupOptions<TFrom, TAsElement, TOutput> options = null,
  539. ExpressionTranslationOptions translationOptions = null)
  540. where TAs : IEnumerable<TAsElement>
  541. {
  542. Ensure.IsNotNull(pipeline, nameof(pipeline));
  543. return pipeline.AppendStage(PipelineStageDefinitionBuilder.GraphLookup(from, connectFromField, connectToField, startWith, @as, depthField, options, translationOptions));
  544. }
  545. /// <summary>
  546. /// Appends a $group stage to the pipeline.
  547. /// </summary>
  548. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  549. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  550. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  551. /// <param name="pipeline">The pipeline.</param>
  552. /// <param name="group">The group projection.</param>
  553. /// <returns>
  554. /// A new pipeline with an additional stage.
  555. /// </returns>
  556. public static PipelineDefinition<TInput, TOutput> Group<TInput, TIntermediate, TOutput>(
  557. this PipelineDefinition<TInput, TIntermediate> pipeline,
  558. ProjectionDefinition<TIntermediate, TOutput> group)
  559. {
  560. Ensure.IsNotNull(pipeline, nameof(pipeline));
  561. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(group));
  562. }
  563. /// <summary>
  564. /// Appends a group stage to the pipeline.
  565. /// </summary>
  566. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  567. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  568. /// <param name="pipeline">The pipeline.</param>
  569. /// <param name="group">The group projection.</param>
  570. /// <returns>
  571. /// The fluent aggregate interface.
  572. /// </returns>
  573. public static PipelineDefinition<TInput, BsonDocument> Group<TInput, TIntermediate>(
  574. this PipelineDefinition<TInput, TIntermediate> pipeline,
  575. ProjectionDefinition<TIntermediate, BsonDocument> group)
  576. {
  577. Ensure.IsNotNull(pipeline, nameof(pipeline));
  578. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(group));
  579. }
  580. /// <summary>
  581. /// Appends a group stage to the pipeline.
  582. /// </summary>
  583. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  584. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  585. /// <typeparam name="TKey">The type of the key.</typeparam>
  586. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  587. /// <param name="pipeline">The pipeline.</param>
  588. /// <param name="id">The id.</param>
  589. /// <param name="group">The group projection.</param>
  590. /// <param name="translationOptions">The translation options.</param>
  591. /// <returns>
  592. /// The fluent aggregate interface.
  593. /// </returns>
  594. public static PipelineDefinition<TInput, TOutput> Group<TInput, TIntermediate, TKey, TOutput>(
  595. this PipelineDefinition<TInput, TIntermediate> pipeline,
  596. Expression<Func<TIntermediate, TKey>> id,
  597. Expression<Func<IGrouping<TKey, TIntermediate>, TOutput>> group,
  598. ExpressionTranslationOptions translationOptions = null)
  599. {
  600. Ensure.IsNotNull(pipeline, nameof(pipeline));
  601. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Group(id, group, translationOptions));
  602. }
  603. /// <summary>
  604. /// Appends a $limit stage to the pipeline.
  605. /// </summary>
  606. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  607. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  608. /// <param name="pipeline">The pipeline.</param>
  609. /// <param name="limit">The limit.</param>
  610. /// <returns>
  611. /// A new pipeline with an additional stage.
  612. /// </returns>
  613. public static PipelineDefinition<TInput, TOutput> Limit<TInput, TOutput>(
  614. this PipelineDefinition<TInput, TOutput> pipeline,
  615. int limit)
  616. {
  617. Ensure.IsNotNull(pipeline, nameof(pipeline));
  618. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Limit<TOutput>(limit));
  619. }
  620. /// <summary>
  621. /// Appends a $lookup stage to the pipeline.
  622. /// </summary>
  623. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  624. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  625. /// <typeparam name="TForeignDocument">The type of the foreign collection documents.</typeparam>
  626. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  627. /// <param name="pipeline">The pipeline.</param>
  628. /// <param name="foreignCollection">The foreign collection.</param>
  629. /// <param name="localField">The local field.</param>
  630. /// <param name="foreignField">The foreign field.</param>
  631. /// <param name="as">The "as" field.</param>
  632. /// <param name="options">The options.</param>
  633. /// <returns>
  634. /// A new pipeline with an additional stage.
  635. /// </returns>
  636. public static PipelineDefinition<TInput, TOutput> Lookup<TInput, TIntermediate, TForeignDocument, TOutput>(
  637. this PipelineDefinition<TInput, TIntermediate> pipeline,
  638. IMongoCollection<TForeignDocument> foreignCollection,
  639. FieldDefinition<TIntermediate> localField,
  640. FieldDefinition<TForeignDocument> foreignField,
  641. FieldDefinition<TOutput> @as,
  642. AggregateLookupOptions<TForeignDocument, TOutput> options = null)
  643. {
  644. Ensure.IsNotNull(pipeline, nameof(pipeline));
  645. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup(foreignCollection, localField, foreignField, @as, options));
  646. }
  647. /// <summary>
  648. /// Appends a lookup stage to the pipeline.
  649. /// </summary>
  650. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  651. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  652. /// <typeparam name="TForeignDocument">The type of the foreign collection documents.</typeparam>
  653. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  654. /// <param name="pipeline">The pipeline.</param>
  655. /// <param name="foreignCollection">The foreign collection.</param>
  656. /// <param name="localField">The local field.</param>
  657. /// <param name="foreignField">The foreign field.</param>
  658. /// <param name="as">The "as" field.</param>
  659. /// <param name="options">The options.</param>
  660. /// <returns>
  661. /// The fluent aggregate interface.
  662. /// </returns>
  663. public static PipelineDefinition<TInput, TOutput> Lookup<TInput, TIntermediate, TForeignDocument, TOutput>(
  664. this PipelineDefinition<TInput, TIntermediate> pipeline,
  665. IMongoCollection<TForeignDocument> foreignCollection,
  666. Expression<Func<TIntermediate, object>> localField,
  667. Expression<Func<TForeignDocument, object>> foreignField,
  668. Expression<Func<TOutput, object>> @as,
  669. AggregateLookupOptions<TForeignDocument, TOutput> options = null)
  670. {
  671. Ensure.IsNotNull(pipeline, nameof(pipeline));
  672. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup(foreignCollection, localField, foreignField, @as, options));
  673. }
  674. /// <summary>
  675. /// Appends a $lookup stage to the pipeline.
  676. /// </summary>
  677. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  678. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  679. /// <typeparam name="TForeignDocument">The type of the foreign collection documents.</typeparam>
  680. /// <typeparam name="TAsElement">The type of the as field elements.</typeparam>
  681. /// <typeparam name="TAs">The type of the as field.</typeparam>
  682. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  683. /// <param name="pipeline">The pipeline.</param>
  684. /// <param name="foreignCollection">The foreign collection.</param>
  685. /// <param name="let">The "let" definition.</param>
  686. /// <param name="lookupPipeline">The lookup pipeline.</param>
  687. /// <param name="as">The as field in <typeparamref name="TOutput" /> in which to place the results of the lookup pipeline.</param>
  688. /// <param name="options">The options.</param>
  689. /// <returns>The stage.</returns>
  690. public static PipelineDefinition<TInput, TOutput> Lookup<TInput, TIntermediate, TForeignDocument, TAsElement, TAs, TOutput>(
  691. this PipelineDefinition<TInput, TIntermediate> pipeline,
  692. IMongoCollection<TForeignDocument> foreignCollection,
  693. BsonDocument let,
  694. PipelineDefinition<TForeignDocument, TAsElement> lookupPipeline,
  695. FieldDefinition<TOutput, TAs> @as,
  696. AggregateLookupOptions<TForeignDocument, TOutput> options = null)
  697. where TAs : IEnumerable<TAsElement>
  698. {
  699. Ensure.IsNotNull(pipeline, nameof(pipeline));
  700. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup<TIntermediate, TForeignDocument, TAsElement, TAs, TOutput>(
  701. foreignCollection,
  702. let,
  703. lookupPipeline,
  704. @as,
  705. options
  706. ));
  707. }
  708. /// <summary>
  709. /// Appends a $lookup stage to the pipeline.
  710. /// </summary>
  711. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  712. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  713. /// <typeparam name="TForeignDocument">The type of the foreign collection documents.</typeparam>
  714. /// <typeparam name="TAsElement">The type of the as field elements.</typeparam>
  715. /// <typeparam name="TAs">The type of the as field.</typeparam>
  716. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  717. /// <param name="pipeline">The pipeline.</param>
  718. /// <param name="foreignCollection">The foreign collection.</param>
  719. /// <param name="let">The "let" definition.</param>
  720. /// <param name="lookupPipeline">The lookup pipeline.</param>
  721. /// <param name="as">The as field in <typeparamref name="TOutput" /> in which to place the results of the lookup pipeline.</param>
  722. /// <param name="options">The options.</param>
  723. /// <returns>The stage.</returns>
  724. public static PipelineDefinition<TInput, TOutput> Lookup<TInput, TIntermediate, TForeignDocument, TAsElement, TAs, TOutput>(
  725. this PipelineDefinition<TInput, TIntermediate> pipeline,
  726. IMongoCollection<TForeignDocument> foreignCollection,
  727. BsonDocument let,
  728. PipelineDefinition<TForeignDocument, TAsElement> lookupPipeline,
  729. Expression<Func<TOutput, TAs>> @as,
  730. AggregateLookupOptions<TForeignDocument, TOutput> options = null)
  731. where TAs : IEnumerable<TAsElement>
  732. {
  733. Ensure.IsNotNull(pipeline, nameof(pipeline));
  734. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Lookup<TIntermediate, TForeignDocument, TAsElement, TAs, TOutput>(
  735. foreignCollection,
  736. let,
  737. lookupPipeline,
  738. @as,
  739. options
  740. ));
  741. }
  742. /// <summary>
  743. /// Appends a $match stage to the pipeline.
  744. /// </summary>
  745. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  746. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  747. /// <param name="pipeline">The pipeline.</param>
  748. /// <param name="filter">The filter.</param>
  749. /// <returns>
  750. /// A new pipeline with an additional stage.
  751. /// </returns>
  752. public static PipelineDefinition<TInput, TOutput> Match<TInput, TOutput>(
  753. this PipelineDefinition<TInput, TOutput> pipeline,
  754. FilterDefinition<TOutput> filter)
  755. {
  756. Ensure.IsNotNull(pipeline, nameof(pipeline));
  757. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Match(filter));
  758. }
  759. /// <summary>
  760. /// Appends a match stage to the pipeline.
  761. /// </summary>
  762. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  763. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  764. /// <param name="pipeline">The pipeline.</param>
  765. /// <param name="filter">The filter.</param>
  766. /// <returns>
  767. /// The fluent aggregate interface.
  768. /// </returns>
  769. public static PipelineDefinition<TInput, TOutput> Match<TInput, TOutput>(
  770. this PipelineDefinition<TInput, TOutput> pipeline,
  771. Expression<Func<TOutput, bool>> filter)
  772. {
  773. Ensure.IsNotNull(pipeline, nameof(pipeline));
  774. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Match(filter));
  775. }
  776. /// <summary>
  777. /// Appends a $match stage to the pipeline to select documents of a certain type.
  778. /// </summary>
  779. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  780. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  781. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  782. /// <param name="pipeline">The pipeline.</param>
  783. /// <param name="outputSerializer">The output serializer.</param>
  784. /// <returns>
  785. /// A new pipeline with an additional stage.
  786. /// </returns>
  787. /// <exception cref="System.NotSupportedException"></exception>
  788. public static PipelineDefinition<TInput, TOutput> OfType<TInput, TIntermediate, TOutput>(
  789. this PipelineDefinition<TInput, TIntermediate> pipeline,
  790. IBsonSerializer<TOutput> outputSerializer = null)
  791. where TOutput : TIntermediate
  792. {
  793. Ensure.IsNotNull(pipeline, nameof(pipeline));
  794. return pipeline.AppendStage(PipelineStageDefinitionBuilder.OfType<TIntermediate, TOutput>(outputSerializer));
  795. }
  796. /// <summary>
  797. /// Appends a $out stage to the pipeline.
  798. /// </summary>
  799. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  800. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  801. /// <param name="pipeline">The pipeline.</param>
  802. /// <param name="outputCollection">The output collection.</param>
  803. /// <returns>
  804. /// A new pipeline with an additional stage.
  805. /// </returns>
  806. /// <exception cref="System.NotSupportedException"></exception>
  807. public static PipelineDefinition<TInput, TOutput> Out<TInput, TOutput>(
  808. this PipelineDefinition<TInput, TOutput> pipeline,
  809. IMongoCollection<TOutput> outputCollection)
  810. {
  811. Ensure.IsNotNull(pipeline, nameof(pipeline));
  812. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Out<TOutput>(outputCollection));
  813. }
  814. /// <summary>
  815. /// Appends a $project stage to the pipeline.
  816. /// </summary>
  817. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  818. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  819. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  820. /// <param name="pipeline">The pipeline.</param>
  821. /// <param name="projection">The projection.</param>
  822. /// <returns>
  823. /// A new pipeline with an additional stage.
  824. /// </returns>
  825. /// <exception cref="System.NotSupportedException"></exception>
  826. public static PipelineDefinition<TInput, TOutput> Project<TInput, TIntermediate, TOutput>(
  827. this PipelineDefinition<TInput, TIntermediate> pipeline,
  828. ProjectionDefinition<TIntermediate, TOutput> projection)
  829. {
  830. Ensure.IsNotNull(pipeline, nameof(pipeline));
  831. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection));
  832. }
  833. /// <summary>
  834. /// Appends a project stage to the pipeline.
  835. /// </summary>
  836. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  837. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  838. /// <param name="pipeline">The pipeline.</param>
  839. /// <param name="projection">The projection.</param>
  840. /// <returns>
  841. /// The fluent aggregate interface.
  842. /// </returns>
  843. public static PipelineDefinition<TInput, BsonDocument> Project<TInput, TIntermediate>(
  844. this PipelineDefinition<TInput, TIntermediate> pipeline,
  845. ProjectionDefinition<TIntermediate, BsonDocument> projection)
  846. {
  847. Ensure.IsNotNull(pipeline, nameof(pipeline));
  848. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection));
  849. }
  850. /// <summary>
  851. /// Appends a project stage to the pipeline.
  852. /// </summary>
  853. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  854. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  855. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  856. /// <param name="pipeline">The pipeline.</param>
  857. /// <param name="projection">The projection.</param>
  858. /// <param name="translationOptions">The translation options.</param>
  859. /// <returns>
  860. /// The fluent aggregate interface.
  861. /// </returns>
  862. public static PipelineDefinition<TInput, TOutput> Project<TInput, TIntermediate, TOutput>(
  863. this PipelineDefinition<TInput, TIntermediate> pipeline,
  864. Expression<Func<TIntermediate, TOutput>> projection,
  865. ExpressionTranslationOptions translationOptions = null)
  866. {
  867. Ensure.IsNotNull(pipeline, nameof(pipeline));
  868. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Project(projection, translationOptions));
  869. }
  870. /// <summary>
  871. /// Appends a $replaceRoot stage to the pipeline.
  872. /// </summary>
  873. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  874. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  875. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  876. /// <param name="pipeline">The pipeline.</param>
  877. /// <param name="newRoot">The new root.</param>
  878. /// <returns>
  879. /// A new pipeline with an additional stage.
  880. /// </returns>
  881. public static PipelineDefinition<TInput, TOutput> ReplaceRoot<TInput, TIntermediate, TOutput>(
  882. this PipelineDefinition<TInput, TIntermediate> pipeline,
  883. AggregateExpressionDefinition<TIntermediate, TOutput> newRoot)
  884. {
  885. Ensure.IsNotNull(pipeline, nameof(pipeline));
  886. return pipeline.AppendStage(PipelineStageDefinitionBuilder.ReplaceRoot(newRoot));
  887. }
  888. /// <summary>
  889. /// Appends a $replaceRoot stage to the pipeline.
  890. /// </summary>
  891. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  892. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  893. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  894. /// <param name="pipeline">The pipeline.</param>
  895. /// <param name="newRoot">The new root.</param>
  896. /// <param name="translationOptions">The translation options.</param>
  897. /// <returns>
  898. /// The fluent aggregate interface.
  899. /// </returns>
  900. public static PipelineDefinition<TInput, TOutput> ReplaceRoot<TInput, TIntermediate, TOutput>(
  901. this PipelineDefinition<TInput, TIntermediate> pipeline,
  902. Expression<Func<TIntermediate, TOutput>> newRoot,
  903. ExpressionTranslationOptions translationOptions = null)
  904. {
  905. Ensure.IsNotNull(pipeline, nameof(pipeline));
  906. return pipeline.AppendStage(PipelineStageDefinitionBuilder.ReplaceRoot(newRoot, translationOptions));
  907. }
  908. /// <summary>
  909. /// Appends a $skip stage to the pipeline.
  910. /// </summary>
  911. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  912. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  913. /// <param name="pipeline">The pipeline.</param>
  914. /// <param name="skip">The number of documents to skip.</param>
  915. /// <returns>
  916. /// A new pipeline with an additional stage.
  917. /// </returns>
  918. public static PipelineDefinition<TInput, TOutput> Skip<TInput, TOutput>(
  919. this PipelineDefinition<TInput, TOutput> pipeline,
  920. int skip)
  921. {
  922. Ensure.IsNotNull(pipeline, nameof(pipeline));
  923. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Skip<TOutput>(skip));
  924. }
  925. /// <summary>
  926. /// Appends a $sort stage to the pipeline.
  927. /// </summary>
  928. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  929. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  930. /// <param name="pipeline">The pipeline.</param>
  931. /// <param name="sort">The sort definition.</param>
  932. /// <returns>
  933. /// A new pipeline with an additional stage.
  934. /// </returns>
  935. public static PipelineDefinition<TInput, TOutput> Sort<TInput, TOutput>(
  936. this PipelineDefinition<TInput, TOutput> pipeline,
  937. SortDefinition<TOutput> sort)
  938. {
  939. Ensure.IsNotNull(pipeline, nameof(pipeline));
  940. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Sort(sort));
  941. }
  942. /// <summary>
  943. /// Appends a $sortByCount stage to the pipeline.
  944. /// </summary>
  945. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  946. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  947. /// <typeparam name="TValue">The type of the values.</typeparam>
  948. /// <param name="pipeline">The pipeline.</param>
  949. /// <param name="value">The value expression.</param>
  950. /// <returns>
  951. /// A new pipeline with an additional stage.
  952. /// </returns>
  953. public static PipelineDefinition<TInput, AggregateSortByCountResult<TValue>> SortByCount<TInput, TIntermediate, TValue>(
  954. this PipelineDefinition<TInput, TIntermediate> pipeline,
  955. AggregateExpressionDefinition<TIntermediate, TValue> value)
  956. {
  957. Ensure.IsNotNull(pipeline, nameof(pipeline));
  958. return pipeline.AppendStage(PipelineStageDefinitionBuilder.SortByCount(value));
  959. }
  960. /// <summary>
  961. /// Appends a sortByCount stage to the pipeline.
  962. /// </summary>
  963. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  964. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  965. /// <typeparam name="TValue">The type of the values.</typeparam>
  966. /// <param name="pipeline">The pipeline.</param>
  967. /// <param name="value">The value expression.</param>
  968. /// <param name="translationOptions">The translation options.</param>
  969. /// <returns>
  970. /// The fluent aggregate interface.
  971. /// </returns>
  972. public static PipelineDefinition<TInput, AggregateSortByCountResult<TValue>> SortByCount<TInput, TIntermediate, TValue>(
  973. this PipelineDefinition<TInput, TIntermediate> pipeline,
  974. Expression<Func<TIntermediate, TValue>> value,
  975. ExpressionTranslationOptions translationOptions = null)
  976. {
  977. Ensure.IsNotNull(pipeline, nameof(pipeline));
  978. return pipeline.AppendStage(PipelineStageDefinitionBuilder.SortByCount(value, translationOptions));
  979. }
  980. /// <summary>
  981. /// Appends an $unwind stage to the pipeline.
  982. /// </summary>
  983. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  984. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  985. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  986. /// <param name="pipeline">The pipeline.</param>
  987. /// <param name="field">The field.</param>
  988. /// <param name="options">The options.</param>
  989. /// <returns>
  990. /// A new pipeline with an additional stage.
  991. /// </returns>
  992. public static PipelineDefinition<TInput, TOutput> Unwind<TInput, TIntermediate, TOutput>(
  993. this PipelineDefinition<TInput, TIntermediate> pipeline,
  994. FieldDefinition<TIntermediate> field,
  995. AggregateUnwindOptions<TOutput> options = null)
  996. {
  997. Ensure.IsNotNull(pipeline, nameof(pipeline));
  998. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  999. }
  1000. /// <summary>
  1001. /// Appends an unwind stage to the pipeline.
  1002. /// </summary>
  1003. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1004. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1005. /// <param name="pipeline">The pipeline.</param>
  1006. /// <param name="field">The field to unwind.</param>
  1007. /// <param name="options">The options.</param>
  1008. /// <returns>
  1009. /// The fluent aggregate interface.
  1010. /// </returns>
  1011. public static PipelineDefinition<TInput, BsonDocument> Unwind<TInput, TIntermediate>(
  1012. this PipelineDefinition<TInput, TIntermediate> pipeline,
  1013. FieldDefinition<TIntermediate> field,
  1014. AggregateUnwindOptions<BsonDocument> options = null)
  1015. {
  1016. Ensure.IsNotNull(pipeline, nameof(pipeline));
  1017. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  1018. }
  1019. /// <summary>
  1020. /// Appends an unwind stage to the pipeline.
  1021. /// </summary>
  1022. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1023. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1024. /// <param name="pipeline">The pipeline.</param>
  1025. /// <param name="field">The field to unwind.</param>
  1026. /// <param name="options">The options.</param>
  1027. /// <returns>
  1028. /// The fluent aggregate interface.
  1029. /// </returns>
  1030. public static PipelineDefinition<TInput, BsonDocument> Unwind<TInput, TIntermediate>(
  1031. this PipelineDefinition<TInput, TIntermediate> pipeline,
  1032. Expression<Func<TIntermediate, object>> field,
  1033. AggregateUnwindOptions<BsonDocument> options = null)
  1034. {
  1035. Ensure.IsNotNull(pipeline, nameof(pipeline));
  1036. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  1037. }
  1038. /// <summary>
  1039. /// Appends an unwind stage to the pipeline.
  1040. /// </summary>
  1041. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1042. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1043. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  1044. /// <param name="pipeline">The pipeline.</param>
  1045. /// <param name="field">The field to unwind.</param>
  1046. /// <param name="options">The options.</param>
  1047. /// <returns>
  1048. /// The fluent aggregate interface.
  1049. /// </returns>
  1050. public static PipelineDefinition<TInput, TOutput> Unwind<TInput, TIntermediate, TOutput>(
  1051. this PipelineDefinition<TInput, TIntermediate> pipeline,
  1052. Expression<Func<TIntermediate, object>> field,
  1053. AggregateUnwindOptions<TOutput> options = null)
  1054. {
  1055. Ensure.IsNotNull(pipeline, nameof(pipeline));
  1056. return pipeline.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, options));
  1057. }
  1058. }
  1059. /// <summary>
  1060. /// Represents a pipeline consisting of an existing pipeline with one additional stage appended.
  1061. /// </summary>
  1062. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1063. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1064. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  1065. public sealed class AppendedStagePipelineDefinition<TInput, TIntermediate, TOutput> : PipelineDefinition<TInput, TOutput>
  1066. {
  1067. private readonly IBsonSerializer<TOutput> _outputSerializer;
  1068. private readonly PipelineDefinition<TInput, TIntermediate> _pipeline;
  1069. private readonly PipelineStageDefinition<TIntermediate, TOutput> _stage;
  1070. /// <summary>
  1071. /// Initializes a new instance of the <see cref="AppendedStagePipelineDefinition{TInput, TIntermediate, TOutput}" /> class.
  1072. /// </summary>
  1073. /// <param name="pipeline">The pipeline.</param>
  1074. /// <param name="stage">The stage.</param>
  1075. /// <param name="outputSerializer">The output serializer.</param>
  1076. public AppendedStagePipelineDefinition(
  1077. PipelineDefinition<TInput, TIntermediate> pipeline,
  1078. PipelineStageDefinition<TIntermediate, TOutput> stage,
  1079. IBsonSerializer<TOutput> outputSerializer = null)
  1080. {
  1081. _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline));
  1082. _stage = Ensure.IsNotNull(stage, nameof(stage));
  1083. _outputSerializer = outputSerializer; // can be null
  1084. }
  1085. /// <inheritdoc/>
  1086. public override IBsonSerializer<TOutput> OutputSerializer => _outputSerializer;
  1087. /// <inheritdoc/>
  1088. public override IEnumerable<IPipelineStageDefinition> Stages => _pipeline.Stages.Concat(new[] { _stage });
  1089. /// <inheritdoc/>
  1090. public override RenderedPipelineDefinition<TOutput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1091. {
  1092. var renderedPipeline = _pipeline.Render(inputSerializer, serializerRegistry);
  1093. var renderedStage = _stage.Render(renderedPipeline.OutputSerializer, serializerRegistry);
  1094. var documents = renderedPipeline.Documents.Concat(new[] { renderedStage.Document });
  1095. var outputSerializer = _outputSerializer ?? renderedStage.OutputSerializer;
  1096. return new RenderedPipelineDefinition<TOutput>(documents, outputSerializer);
  1097. }
  1098. }
  1099. /// <summary>
  1100. /// Represents an empty pipeline.
  1101. /// </summary>
  1102. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1103. public sealed class EmptyPipelineDefinition<TInput> : PipelineDefinition<TInput, TInput>
  1104. {
  1105. private readonly IBsonSerializer<TInput> _inputSerializer;
  1106. /// <summary>
  1107. /// Initializes a new instance of the <see cref="EmptyPipelineDefinition{TOutput}"/> class.
  1108. /// </summary>
  1109. /// <param name="inputSerializer">The output serializer.</param>
  1110. public EmptyPipelineDefinition(IBsonSerializer<TInput> inputSerializer = null)
  1111. {
  1112. _inputSerializer = inputSerializer; // can be null
  1113. }
  1114. /// <inheritdoc/>
  1115. public override IBsonSerializer<TInput> OutputSerializer => _inputSerializer;
  1116. /// <inheritdoc/>
  1117. public override IEnumerable<IPipelineStageDefinition> Stages => Enumerable.Empty<IPipelineStageDefinition>();
  1118. /// <inheritdoc/>
  1119. public override RenderedPipelineDefinition<TInput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1120. {
  1121. var documents = Enumerable.Empty<BsonDocument>();
  1122. return new RenderedPipelineDefinition<TInput>(documents, _inputSerializer ?? inputSerializer);
  1123. }
  1124. }
  1125. /// <summary>
  1126. /// Represents a pipeline consisting of an existing pipeline with one additional stage prepended.
  1127. /// </summary>
  1128. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1129. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1130. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  1131. public sealed class PrependedStagePipelineDefinition<TInput, TIntermediate, TOutput> : PipelineDefinition<TInput, TOutput>
  1132. {
  1133. private readonly IBsonSerializer<TOutput> _outputSerializer;
  1134. private readonly PipelineDefinition<TIntermediate, TOutput> _pipeline;
  1135. private readonly PipelineStageDefinition<TInput, TIntermediate> _stage;
  1136. /// <summary>
  1137. /// Initializes a new instance of the <see cref="PrependedStagePipelineDefinition{TInput, TIntermediate, TOutput}" /> class.
  1138. /// </summary>
  1139. /// <param name="stage">The stage.</param>
  1140. /// <param name="pipeline">The pipeline.</param>
  1141. /// <param name="outputSerializer">The output serializer.</param>
  1142. public PrependedStagePipelineDefinition(
  1143. PipelineStageDefinition<TInput, TIntermediate> stage,
  1144. PipelineDefinition<TIntermediate, TOutput> pipeline,
  1145. IBsonSerializer<TOutput> outputSerializer = null)
  1146. {
  1147. _stage = Ensure.IsNotNull(stage, nameof(stage));
  1148. _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline));
  1149. _outputSerializer = outputSerializer; // can be null
  1150. }
  1151. /// <inheritdoc/>
  1152. public override IBsonSerializer<TOutput> OutputSerializer => _outputSerializer;
  1153. /// <inheritdoc/>
  1154. public override IEnumerable<IPipelineStageDefinition> Stages => new[] { _stage }.Concat(_pipeline.Stages);
  1155. /// <inheritdoc/>
  1156. public override RenderedPipelineDefinition<TOutput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1157. {
  1158. var renderedStage = _stage.Render(inputSerializer, serializerRegistry);
  1159. var renderedPipeline = _pipeline.Render(renderedStage.OutputSerializer, serializerRegistry);
  1160. var documents = new[] { renderedStage.Document }.Concat(renderedPipeline.Documents);
  1161. var outputSerializer = _outputSerializer ?? renderedPipeline.OutputSerializer;
  1162. return new RenderedPipelineDefinition<TOutput>(documents, outputSerializer);
  1163. }
  1164. }
  1165. /// <summary>
  1166. /// Represents a pipeline with the output serializer replaced.
  1167. /// </summary>
  1168. /// <typeparam name="TInput">The type of the input documents.</typeparam>
  1169. /// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
  1170. /// <typeparam name="TOutput">The type of the output documents.</typeparam>
  1171. /// <seealso cref="MongoDB.Driver.PipelineDefinition{TInput, TOutput}" />
  1172. public sealed class ReplaceOutputSerializerPipelineDefinition<TInput, TIntermediate, TOutput> : PipelineDefinition<TInput, TOutput>
  1173. {
  1174. private readonly IBsonSerializer<TOutput> _outputSerializer;
  1175. private readonly PipelineDefinition<TInput, TIntermediate> _pipeline;
  1176. /// <summary>
  1177. /// Initializes a new instance of the <see cref="ReplaceOutputSerializerPipelineDefinition{TInput, TIntermediate, TOutput}"/> class.
  1178. /// </summary>
  1179. /// <param name="pipeline">The pipeline.</param>
  1180. /// <param name="outputSerializer">The output serializer.</param>
  1181. public ReplaceOutputSerializerPipelineDefinition(
  1182. PipelineDefinition<TInput, TIntermediate> pipeline,
  1183. IBsonSerializer<TOutput> outputSerializer = null)
  1184. {
  1185. _pipeline = Ensure.IsNotNull(pipeline, nameof(pipeline));
  1186. _outputSerializer = outputSerializer; // can be null
  1187. }
  1188. /// <inheritdoc/>
  1189. public override IBsonSerializer<TOutput> OutputSerializer => _outputSerializer;
  1190. /// <inheritdoc/>
  1191. public override IEnumerable<IPipelineStageDefinition> Stages => _pipeline.Stages;
  1192. /// <inheritdoc/>
  1193. public override RenderedPipelineDefinition<TOutput> Render(IBsonSerializer<TInput> inputSerializer, IBsonSerializerRegistry serializerRegistry)
  1194. {
  1195. var renderedPipeline = _pipeline.Render(inputSerializer, serializerRegistry);
  1196. var outputSerializer = _outputSerializer ?? serializerRegistry.GetSerializer<TOutput>();
  1197. return new RenderedPipelineDefinition<TOutput>(renderedPipeline.Documents, outputSerializer);
  1198. }
  1199. }
  1200. }