UpdateDefinitionBuilder.cs 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675
  1. /* Copyright 2010-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.IO;
  21. using MongoDB.Bson.Serialization;
  22. using MongoDB.Driver.Core.Misc;
  23. namespace MongoDB.Driver
  24. {
  25. /// <summary>
  26. /// Extension methods for UpdateDefinition.
  27. /// </summary>
  28. public static class UpdateDefinitionExtensions
  29. {
  30. /// <summary>
  31. /// Combines an existing update with an add to set operator.
  32. /// </summary>
  33. /// <typeparam name="TDocument">The type of the document.</typeparam>
  34. /// <typeparam name="TItem">The type of the item.</typeparam>
  35. /// <param name="update">The update.</param>
  36. /// <param name="field">The field.</param>
  37. /// <param name="value">The value.</param>
  38. /// <returns>
  39. /// A combined update.
  40. /// </returns>
  41. public static UpdateDefinition<TDocument> AddToSet<TDocument, TItem>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, TItem value)
  42. {
  43. var builder = Builders<TDocument>.Update;
  44. return builder.Combine(update, builder.AddToSet<TItem>(field, value));
  45. }
  46. /// <summary>
  47. /// Combines an existing update with an add to set operator.
  48. /// </summary>
  49. /// <typeparam name="TDocument">The type of the document.</typeparam>
  50. /// <typeparam name="TItem">The type of the item.</typeparam>
  51. /// <param name="update">The update.</param>
  52. /// <param name="field">The field.</param>
  53. /// <param name="value">The value.</param>
  54. /// <returns>
  55. /// A combined update.
  56. /// </returns>
  57. public static UpdateDefinition<TDocument> AddToSet<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, TItem value)
  58. {
  59. var builder = Builders<TDocument>.Update;
  60. return builder.Combine(update, builder.AddToSet<TItem>(field, value));
  61. }
  62. /// <summary>
  63. /// Combines an existing update with an add to set operator.
  64. /// </summary>
  65. /// <typeparam name="TDocument">The type of the document.</typeparam>
  66. /// <typeparam name="TItem">The type of the item.</typeparam>
  67. /// <param name="update">The update.</param>
  68. /// <param name="field">The field.</param>
  69. /// <param name="values">The values.</param>
  70. /// <returns>
  71. /// A combined update.
  72. /// </returns>
  73. public static UpdateDefinition<TDocument> AddToSetEach<TDocument, TItem>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, IEnumerable<TItem> values)
  74. {
  75. var builder = Builders<TDocument>.Update;
  76. return builder.Combine(update, builder.AddToSetEach<TItem>(field, values));
  77. }
  78. /// <summary>
  79. /// Combines an existing update with an add to set operator.
  80. /// </summary>
  81. /// <typeparam name="TDocument">The type of the document.</typeparam>
  82. /// <typeparam name="TItem">The type of the item.</typeparam>
  83. /// <param name="update">The update.</param>
  84. /// <param name="field">The field.</param>
  85. /// <param name="values">The values.</param>
  86. /// <returns>
  87. /// A combined update.
  88. /// </returns>
  89. public static UpdateDefinition<TDocument> AddToSetEach<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, IEnumerable<TItem> values)
  90. {
  91. var builder = Builders<TDocument>.Update;
  92. return builder.Combine(update, builder.AddToSetEach<TItem>(field, values));
  93. }
  94. /// <summary>
  95. /// Combines an existing update with a bitwise and operator.
  96. /// </summary>
  97. /// <typeparam name="TDocument">The type of the document.</typeparam>
  98. /// <typeparam name="TField">The type of the field.</typeparam>
  99. /// <param name="update">The update.</param>
  100. /// <param name="field">The field.</param>
  101. /// <param name="value">The value.</param>
  102. /// <returns>
  103. /// A combined update.
  104. /// </returns>
  105. public static UpdateDefinition<TDocument> BitwiseAnd<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  106. {
  107. var builder = Builders<TDocument>.Update;
  108. return builder.Combine(update, builder.BitwiseAnd(field, value));
  109. }
  110. /// <summary>
  111. /// Combines an existing update with a bitwise and operator.
  112. /// </summary>
  113. /// <typeparam name="TDocument">The type of the document.</typeparam>
  114. /// <typeparam name="TField">The type of the field.</typeparam>
  115. /// <param name="update">The update.</param>
  116. /// <param name="field">The field.</param>
  117. /// <param name="value">The value.</param>
  118. /// <returns>
  119. /// A combined update.
  120. /// </returns>
  121. public static UpdateDefinition<TDocument> BitwiseAnd<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  122. {
  123. var builder = Builders<TDocument>.Update;
  124. return builder.Combine(update, builder.BitwiseAnd(field, value));
  125. }
  126. /// <summary>
  127. /// Combines an existing update with a bitwise or operator.
  128. /// </summary>
  129. /// <typeparam name="TDocument">The type of the document.</typeparam>
  130. /// <typeparam name="TField">The type of the field.</typeparam>
  131. /// <param name="update">The update.</param>
  132. /// <param name="field">The field.</param>
  133. /// <param name="value">The value.</param>
  134. /// <returns>
  135. /// A combined update.
  136. /// </returns>
  137. public static UpdateDefinition<TDocument> BitwiseOr<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  138. {
  139. var builder = Builders<TDocument>.Update;
  140. return builder.Combine(update, builder.BitwiseOr(field, value));
  141. }
  142. /// <summary>
  143. /// Combines an existing update with a bitwise or operator.
  144. /// </summary>
  145. /// <typeparam name="TDocument">The type of the document.</typeparam>
  146. /// <typeparam name="TField">The type of the field.</typeparam>
  147. /// <param name="update">The update.</param>
  148. /// <param name="field">The field.</param>
  149. /// <param name="value">The value.</param>
  150. /// <returns>
  151. /// A combined update.
  152. /// </returns>
  153. public static UpdateDefinition<TDocument> BitwiseOr<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  154. {
  155. var builder = Builders<TDocument>.Update;
  156. return builder.Combine(update, builder.BitwiseOr(field, value));
  157. }
  158. /// <summary>
  159. /// Combines an existing update with a bitwise xor operator.
  160. /// </summary>
  161. /// <typeparam name="TDocument">The type of the document.</typeparam>
  162. /// <typeparam name="TField">The type of the field.</typeparam>
  163. /// <param name="update">The update.</param>
  164. /// <param name="field">The field.</param>
  165. /// <param name="value">The value.</param>
  166. /// <returns>
  167. /// A combined update.
  168. /// </returns>
  169. public static UpdateDefinition<TDocument> BitwiseXor<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  170. {
  171. var builder = Builders<TDocument>.Update;
  172. return builder.Combine(update, builder.BitwiseXor(field, value));
  173. }
  174. /// <summary>
  175. /// Combines an existing update with a bitwise xor operator.
  176. /// </summary>
  177. /// <typeparam name="TDocument">The type of the document.</typeparam>
  178. /// <typeparam name="TField">The type of the field.</typeparam>
  179. /// <param name="update">The update.</param>
  180. /// <param name="field">The field.</param>
  181. /// <param name="value">The value.</param>
  182. /// <returns>
  183. /// A combined update.
  184. /// </returns>
  185. public static UpdateDefinition<TDocument> BitwiseXor<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  186. {
  187. var builder = Builders<TDocument>.Update;
  188. return builder.Combine(update, builder.BitwiseXor(field, value));
  189. }
  190. /// <summary>
  191. /// Combines an existing update with a current date operator.
  192. /// </summary>
  193. /// <typeparam name="TDocument">The type of the document.</typeparam>
  194. /// <param name="update">The update.</param>
  195. /// <param name="field">The field.</param>
  196. /// <param name="type">The type.</param>
  197. /// <returns>
  198. /// A combined update.
  199. /// </returns>
  200. public static UpdateDefinition<TDocument> CurrentDate<TDocument>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, UpdateDefinitionCurrentDateType? type = null)
  201. {
  202. var builder = Builders<TDocument>.Update;
  203. return builder.Combine(update, builder.CurrentDate(field, type));
  204. }
  205. /// <summary>
  206. /// Combines an existing update with a current date operator.
  207. /// </summary>
  208. /// <typeparam name="TDocument">The type of the document.</typeparam>
  209. /// <param name="update">The update.</param>
  210. /// <param name="field">The field.</param>
  211. /// <param name="type">The type.</param>
  212. /// <returns>
  213. /// A combined update.
  214. /// </returns>
  215. public static UpdateDefinition<TDocument> CurrentDate<TDocument>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, object>> field, UpdateDefinitionCurrentDateType? type = null)
  216. {
  217. var builder = Builders<TDocument>.Update;
  218. return builder.Combine(update, builder.CurrentDate(field, type));
  219. }
  220. /// <summary>
  221. /// Combines an existing update with an increment operator.
  222. /// </summary>
  223. /// <typeparam name="TDocument">The type of the document.</typeparam>
  224. /// <typeparam name="TField">The type of the field.</typeparam>
  225. /// <param name="update">The update.</param>
  226. /// <param name="field">The field.</param>
  227. /// <param name="value">The value.</param>
  228. /// <returns>
  229. /// A combined update.
  230. /// </returns>
  231. public static UpdateDefinition<TDocument> Inc<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  232. {
  233. var builder = Builders<TDocument>.Update;
  234. return builder.Combine(update, builder.Inc(field, value));
  235. }
  236. /// <summary>
  237. /// Combines an existing update with an increment operator.
  238. /// </summary>
  239. /// <typeparam name="TDocument">The type of the document.</typeparam>
  240. /// <typeparam name="TField">The type of the field.</typeparam>
  241. /// <param name="update">The update.</param>
  242. /// <param name="field">The field.</param>
  243. /// <param name="value">The value.</param>
  244. /// <returns>
  245. /// A combined update.
  246. /// </returns>
  247. public static UpdateDefinition<TDocument> Inc<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  248. {
  249. var builder = Builders<TDocument>.Update;
  250. return builder.Combine(update, builder.Inc(field, value));
  251. }
  252. /// <summary>
  253. /// Combines an existing update with a max operator.
  254. /// </summary>
  255. /// <typeparam name="TDocument">The type of the document.</typeparam>
  256. /// <typeparam name="TField">The type of the field.</typeparam>
  257. /// <param name="update">The update.</param>
  258. /// <param name="field">The field.</param>
  259. /// <param name="value">The value.</param>
  260. /// <returns>
  261. /// A combined update.
  262. /// </returns>
  263. public static UpdateDefinition<TDocument> Max<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  264. {
  265. var builder = Builders<TDocument>.Update;
  266. return builder.Combine(update, builder.Max(field, value));
  267. }
  268. /// <summary>
  269. /// Combines an existing update with a max operator.
  270. /// </summary>
  271. /// <typeparam name="TDocument">The type of the document.</typeparam>
  272. /// <typeparam name="TField">The type of the field.</typeparam>
  273. /// <param name="update">The update.</param>
  274. /// <param name="field">The field.</param>
  275. /// <param name="value">The value.</param>
  276. /// <returns>
  277. /// A combined update.
  278. /// </returns>
  279. public static UpdateDefinition<TDocument> Max<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  280. {
  281. var builder = Builders<TDocument>.Update;
  282. return builder.Combine(update, builder.Max(field, value));
  283. }
  284. /// <summary>
  285. /// Combines an existing update with a min operator.
  286. /// </summary>
  287. /// <typeparam name="TDocument">The type of the document.</typeparam>
  288. /// <typeparam name="TField">The type of the field.</typeparam>
  289. /// <param name="update">The update.</param>
  290. /// <param name="field">The field.</param>
  291. /// <param name="value">The value.</param>
  292. /// <returns>
  293. /// A combined update.
  294. /// </returns>
  295. public static UpdateDefinition<TDocument> Min<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  296. {
  297. var builder = Builders<TDocument>.Update;
  298. return builder.Combine(update, builder.Min(field, value));
  299. }
  300. /// <summary>
  301. /// Combines an existing update with a min operator.
  302. /// </summary>
  303. /// <typeparam name="TDocument">The type of the document.</typeparam>
  304. /// <typeparam name="TField">The type of the field.</typeparam>
  305. /// <param name="update">The update.</param>
  306. /// <param name="field">The field.</param>
  307. /// <param name="value">The value.</param>
  308. /// <returns>
  309. /// A combined update.
  310. /// </returns>
  311. public static UpdateDefinition<TDocument> Min<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  312. {
  313. var builder = Builders<TDocument>.Update;
  314. return builder.Combine(update, builder.Min(field, value));
  315. }
  316. /// <summary>
  317. /// Combines an existing update with a multiply operator.
  318. /// </summary>
  319. /// <typeparam name="TDocument">The type of the document.</typeparam>
  320. /// <typeparam name="TField">The type of the field.</typeparam>
  321. /// <param name="update">The update.</param>
  322. /// <param name="field">The field.</param>
  323. /// <param name="value">The value.</param>
  324. /// <returns>
  325. /// A combined update.
  326. /// </returns>
  327. public static UpdateDefinition<TDocument> Mul<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  328. {
  329. var builder = Builders<TDocument>.Update;
  330. return builder.Combine(update, builder.Mul(field, value));
  331. }
  332. /// <summary>
  333. /// Combines an existing update with a multiply operator.
  334. /// </summary>
  335. /// <typeparam name="TDocument">The type of the document.</typeparam>
  336. /// <typeparam name="TField">The type of the field.</typeparam>
  337. /// <param name="update">The update.</param>
  338. /// <param name="field">The field.</param>
  339. /// <param name="value">The value.</param>
  340. /// <returns>
  341. /// A combined update.
  342. /// </returns>
  343. public static UpdateDefinition<TDocument> Mul<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  344. {
  345. var builder = Builders<TDocument>.Update;
  346. return builder.Combine(update, builder.Mul(field, value));
  347. }
  348. /// <summary>
  349. /// Combines an existing update with a pop operator.
  350. /// </summary>
  351. /// <typeparam name="TDocument">The type of the document.</typeparam>
  352. /// <param name="update">The update.</param>
  353. /// <param name="field">The field.</param>
  354. /// <returns>
  355. /// A combined update.
  356. /// </returns>
  357. public static UpdateDefinition<TDocument> PopFirst<TDocument>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field)
  358. {
  359. var builder = Builders<TDocument>.Update;
  360. return builder.Combine(update, builder.PopFirst(field));
  361. }
  362. /// <summary>
  363. /// Combines an existing update with a pop operator.
  364. /// </summary>
  365. /// <typeparam name="TDocument">The type of the document.</typeparam>
  366. /// <param name="update">The update.</param>
  367. /// <param name="field">The field.</param>
  368. /// <returns>
  369. /// A combined update.
  370. /// </returns>
  371. public static UpdateDefinition<TDocument> PopFirst<TDocument>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, object>> field)
  372. {
  373. var builder = Builders<TDocument>.Update;
  374. return builder.Combine(update, builder.PopFirst(field));
  375. }
  376. /// <summary>
  377. /// Combines an existing update with a pop operator.
  378. /// </summary>
  379. /// <typeparam name="TDocument">The type of the document.</typeparam>
  380. /// <param name="update">The update.</param>
  381. /// <param name="field">The field.</param>
  382. /// <returns>
  383. /// A combined update.
  384. /// </returns>
  385. public static UpdateDefinition<TDocument> PopLast<TDocument>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field)
  386. {
  387. var builder = Builders<TDocument>.Update;
  388. return builder.Combine(update, builder.PopLast(field));
  389. }
  390. /// <summary>
  391. /// Combines an existing update with a pop operator.
  392. /// </summary>
  393. /// <typeparam name="TDocument">The type of the document.</typeparam>
  394. /// <param name="update">The update.</param>
  395. /// <param name="field">The field.</param>
  396. /// <returns>
  397. /// A combined update.
  398. /// </returns>
  399. public static UpdateDefinition<TDocument> PopLast<TDocument>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, object>> field)
  400. {
  401. var builder = Builders<TDocument>.Update;
  402. return builder.Combine(update, builder.PopLast(field));
  403. }
  404. /// <summary>
  405. /// Combines an existing update with a pull operator.
  406. /// </summary>
  407. /// <typeparam name="TDocument">The type of the document.</typeparam>
  408. /// <typeparam name="TItem">The type of the item.</typeparam>
  409. /// <param name="update">The update.</param>
  410. /// <param name="field">The field.</param>
  411. /// <param name="value">The value.</param>
  412. /// <returns>
  413. /// A combined update.
  414. /// </returns>
  415. public static UpdateDefinition<TDocument> Pull<TDocument, TItem>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, TItem value)
  416. {
  417. var builder = Builders<TDocument>.Update;
  418. return builder.Combine(update, builder.Pull(field, value));
  419. }
  420. /// <summary>
  421. /// Combines an existing update with a pull operator.
  422. /// </summary>
  423. /// <typeparam name="TDocument">The type of the document.</typeparam>
  424. /// <typeparam name="TItem">The type of the item.</typeparam>
  425. /// <param name="update">The update.</param>
  426. /// <param name="field">The field.</param>
  427. /// <param name="value">The value.</param>
  428. /// <returns>
  429. /// A combined update.
  430. /// </returns>
  431. public static UpdateDefinition<TDocument> Pull<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, TItem value)
  432. {
  433. var builder = Builders<TDocument>.Update;
  434. return builder.Combine(update, builder.Pull(field, value));
  435. }
  436. /// <summary>
  437. /// Combines an existing update with a pull operator.
  438. /// </summary>
  439. /// <typeparam name="TDocument">The type of the document.</typeparam>
  440. /// <typeparam name="TItem">The type of the item.</typeparam>
  441. /// <param name="update">The update.</param>
  442. /// <param name="field">The field.</param>
  443. /// <param name="values">The values.</param>
  444. /// <returns>
  445. /// A combined update.
  446. /// </returns>
  447. public static UpdateDefinition<TDocument> PullAll<TDocument, TItem>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, IEnumerable<TItem> values)
  448. {
  449. var builder = Builders<TDocument>.Update;
  450. return builder.Combine(update, builder.PullAll(field, values));
  451. }
  452. /// <summary>
  453. /// Combines an existing update with a pull operator.
  454. /// </summary>
  455. /// <typeparam name="TDocument">The type of the document.</typeparam>
  456. /// <typeparam name="TItem">The type of the item.</typeparam>
  457. /// <param name="update">The update.</param>
  458. /// <param name="field">The field.</param>
  459. /// <param name="values">The values.</param>
  460. /// <returns>
  461. /// A combined update.
  462. /// </returns>
  463. public static UpdateDefinition<TDocument> PullAll<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, IEnumerable<TItem> values)
  464. {
  465. var builder = Builders<TDocument>.Update;
  466. return builder.Combine(update, builder.PullAll(field, values));
  467. }
  468. /// <summary>
  469. /// Combines an existing update with a pull operator.
  470. /// </summary>
  471. /// <typeparam name="TDocument">The type of the document.</typeparam>
  472. /// <typeparam name="TItem">The type of the item.</typeparam>
  473. /// <param name="update">The update.</param>
  474. /// <param name="field">The field.</param>
  475. /// <param name="filter">The filter.</param>
  476. /// <returns>
  477. /// A combined update.
  478. /// </returns>
  479. public static UpdateDefinition<TDocument> PullFilter<TDocument, TItem>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, FilterDefinition<TItem> filter)
  480. {
  481. var builder = Builders<TDocument>.Update;
  482. return builder.Combine(update, builder.PullFilter(field, filter));
  483. }
  484. /// <summary>
  485. /// Combines an existing update with a pull operator.
  486. /// </summary>
  487. /// <typeparam name="TDocument">The type of the document.</typeparam>
  488. /// <typeparam name="TItem">The type of the item.</typeparam>
  489. /// <param name="update">The update.</param>
  490. /// <param name="field">The field.</param>
  491. /// <param name="filter">The filter.</param>
  492. /// <returns>
  493. /// A combined update.
  494. /// </returns>
  495. public static UpdateDefinition<TDocument> PullFilter<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, FilterDefinition<TItem> filter)
  496. {
  497. var builder = Builders<TDocument>.Update;
  498. return builder.Combine(update, builder.PullFilter(field, filter));
  499. }
  500. /// <summary>
  501. /// Combines an existing update with a pull operator.
  502. /// </summary>
  503. /// <typeparam name="TDocument">The type of the document.</typeparam>
  504. /// <typeparam name="TItem">The type of the item.</typeparam>
  505. /// <param name="update">The update.</param>
  506. /// <param name="field">The field.</param>
  507. /// <param name="filter">The filter.</param>
  508. /// <returns>
  509. /// A combined update.
  510. /// </returns>
  511. public static UpdateDefinition<TDocument> PullFilter<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, Expression<Func<TItem, bool>> filter)
  512. {
  513. var builder = Builders<TDocument>.Update;
  514. return builder.Combine(update, builder.PullFilter(field, filter));
  515. }
  516. /// <summary>
  517. /// Combines an existing update with a push operator.
  518. /// </summary>
  519. /// <typeparam name="TDocument">The type of the document.</typeparam>
  520. /// <typeparam name="TItem">The type of the item.</typeparam>
  521. /// <param name="update">The update.</param>
  522. /// <param name="field">The field.</param>
  523. /// <param name="value">The value.</param>
  524. /// <returns>
  525. /// A combined update.
  526. /// </returns>
  527. public static UpdateDefinition<TDocument> Push<TDocument, TItem>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, TItem value)
  528. {
  529. var builder = Builders<TDocument>.Update;
  530. return builder.Combine(update, builder.Push(field, value));
  531. }
  532. /// <summary>
  533. /// Combines an existing update with a push operator.
  534. /// </summary>
  535. /// <typeparam name="TDocument">The type of the document.</typeparam>
  536. /// <typeparam name="TItem">The type of the item.</typeparam>
  537. /// <param name="update">The update.</param>
  538. /// <param name="field">The field.</param>
  539. /// <param name="value">The value.</param>
  540. /// <returns>
  541. /// A combined update.
  542. /// </returns>
  543. public static UpdateDefinition<TDocument> Push<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, TItem value)
  544. {
  545. var builder = Builders<TDocument>.Update;
  546. return builder.Combine(update, builder.Push(field, value));
  547. }
  548. /// <summary>
  549. /// Combines an existing update with a push operator.
  550. /// </summary>
  551. /// <typeparam name="TDocument">The type of the document.</typeparam>
  552. /// <typeparam name="TItem">The type of the item.</typeparam>
  553. /// <param name="update">The update.</param>
  554. /// <param name="field">The field.</param>
  555. /// <param name="values">The values.</param>
  556. /// <param name="slice">The slice.</param>
  557. /// <param name="position">The position.</param>
  558. /// <param name="sort">The sort.</param>
  559. /// <returns>
  560. /// A combined update.
  561. /// </returns>
  562. public static UpdateDefinition<TDocument> PushEach<TDocument, TItem>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, IEnumerable<TItem> values, int? slice = null, int? position = null, SortDefinition<TItem> sort = null)
  563. {
  564. var builder = Builders<TDocument>.Update;
  565. return builder.Combine(update, builder.PushEach(field, values, slice, position, sort));
  566. }
  567. /// <summary>
  568. /// Combines an existing update with a push operator.
  569. /// </summary>
  570. /// <typeparam name="TDocument">The type of the document.</typeparam>
  571. /// <typeparam name="TItem">The type of the item.</typeparam>
  572. /// <param name="update">The update.</param>
  573. /// <param name="field">The field.</param>
  574. /// <param name="values">The values.</param>
  575. /// <param name="slice">The slice.</param>
  576. /// <param name="position">The position.</param>
  577. /// <param name="sort">The sort.</param>
  578. /// <returns>
  579. /// A combined update.
  580. /// </returns>
  581. public static UpdateDefinition<TDocument> PushEach<TDocument, TItem>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, IEnumerable<TItem>>> field, IEnumerable<TItem> values, int? slice = null, int? position = null, SortDefinition<TItem> sort = null)
  582. {
  583. var builder = Builders<TDocument>.Update;
  584. return builder.Combine(update, builder.PushEach(field, values, slice, position, sort));
  585. }
  586. /// <summary>
  587. /// Combines an existing update with a field renaming operator.
  588. /// </summary>
  589. /// <typeparam name="TDocument">The type of the document.</typeparam>
  590. /// <param name="update">The update.</param>
  591. /// <param name="field">The field.</param>
  592. /// <param name="newName">The new name.</param>
  593. /// <returns>
  594. /// A combined update.
  595. /// </returns>
  596. public static UpdateDefinition<TDocument> Rename<TDocument>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field, string newName)
  597. {
  598. var builder = Builders<TDocument>.Update;
  599. return builder.Combine(update, builder.Rename(field, newName));
  600. }
  601. /// <summary>
  602. /// Combines an existing update with a field renaming operator.
  603. /// </summary>
  604. /// <typeparam name="TDocument">The type of the document.</typeparam>
  605. /// <param name="update">The update.</param>
  606. /// <param name="field">The field.</param>
  607. /// <param name="newName">The new name.</param>
  608. /// <returns>
  609. /// A combined update.
  610. /// </returns>
  611. public static UpdateDefinition<TDocument> Rename<TDocument>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, object>> field, string newName)
  612. {
  613. var builder = Builders<TDocument>.Update;
  614. return builder.Combine(update, builder.Rename(field, newName));
  615. }
  616. /// <summary>
  617. /// Combines an existing update with a set operator.
  618. /// </summary>
  619. /// <typeparam name="TDocument">The type of the document.</typeparam>
  620. /// <typeparam name="TField">The type of the field.</typeparam>
  621. /// <param name="update">The update.</param>
  622. /// <param name="field">The field.</param>
  623. /// <param name="value">The value.</param>
  624. /// <returns>
  625. /// A combined update.
  626. /// </returns>
  627. public static UpdateDefinition<TDocument> Set<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  628. {
  629. var builder = Builders<TDocument>.Update;
  630. return builder.Combine(update, builder.Set(field, value));
  631. }
  632. /// <summary>
  633. /// Combines an existing update with a set operator.
  634. /// </summary>
  635. /// <typeparam name="TDocument">The type of the document.</typeparam>
  636. /// <typeparam name="TField">The type of the field.</typeparam>
  637. /// <param name="update">The update.</param>
  638. /// <param name="field">The field.</param>
  639. /// <param name="value">The value.</param>
  640. /// <returns>
  641. /// A combined update.
  642. /// </returns>
  643. public static UpdateDefinition<TDocument> Set<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  644. {
  645. var builder = Builders<TDocument>.Update;
  646. return builder.Combine(update, builder.Set(field, value));
  647. }
  648. /// <summary>
  649. /// Combines an existing update with a set on insert operator.
  650. /// </summary>
  651. /// <typeparam name="TDocument">The type of the document.</typeparam>
  652. /// <typeparam name="TField">The type of the field.</typeparam>
  653. /// <param name="update">The update.</param>
  654. /// <param name="field">The field.</param>
  655. /// <param name="value">The value.</param>
  656. /// <returns>
  657. /// A combined update.
  658. /// </returns>
  659. public static UpdateDefinition<TDocument> SetOnInsert<TDocument, TField>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument, TField> field, TField value)
  660. {
  661. var builder = Builders<TDocument>.Update;
  662. return builder.Combine(update, builder.SetOnInsert(field, value));
  663. }
  664. /// <summary>
  665. /// Combines an existing update with a set on insert operator.
  666. /// </summary>
  667. /// <typeparam name="TDocument">The type of the document.</typeparam>
  668. /// <typeparam name="TField">The type of the field.</typeparam>
  669. /// <param name="update">The update.</param>
  670. /// <param name="field">The field.</param>
  671. /// <param name="value">The value.</param>
  672. /// <returns>
  673. /// A combined update.
  674. /// </returns>
  675. public static UpdateDefinition<TDocument> SetOnInsert<TDocument, TField>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, TField>> field, TField value)
  676. {
  677. var builder = Builders<TDocument>.Update;
  678. return builder.Combine(update, builder.SetOnInsert(field, value));
  679. }
  680. /// <summary>
  681. /// Combines an existing update with an unset operator.
  682. /// </summary>
  683. /// <typeparam name="TDocument">The type of the document.</typeparam>
  684. /// <param name="update">The update.</param>
  685. /// <param name="field">The field.</param>
  686. /// <returns>
  687. /// A combined update.
  688. /// </returns>
  689. public static UpdateDefinition<TDocument> Unset<TDocument>(this UpdateDefinition<TDocument> update, FieldDefinition<TDocument> field)
  690. {
  691. var builder = Builders<TDocument>.Update;
  692. return builder.Combine(update, builder.Unset(field));
  693. }
  694. /// <summary>
  695. /// Combines an existing update with an unset operator.
  696. /// </summary>
  697. /// <typeparam name="TDocument">The type of the document.</typeparam>
  698. /// <param name="update">The update.</param>
  699. /// <param name="field">The field.</param>
  700. /// <returns>
  701. /// A combined update.
  702. /// </returns>
  703. public static UpdateDefinition<TDocument> Unset<TDocument>(this UpdateDefinition<TDocument> update, Expression<Func<TDocument, object>> field)
  704. {
  705. var builder = Builders<TDocument>.Update;
  706. return builder.Combine(update, builder.Unset(field));
  707. }
  708. }
  709. /// <summary>
  710. /// The type to use for a $currentDate operator.
  711. /// </summary>
  712. public enum UpdateDefinitionCurrentDateType
  713. {
  714. /// <summary>
  715. /// A date.
  716. /// </summary>
  717. Date,
  718. /// <summary>
  719. /// A timestamp.
  720. /// </summary>
  721. Timestamp
  722. }
  723. /// <summary>
  724. /// A builder for an <see cref="UpdateDefinition{TDocument}"/>.
  725. /// </summary>
  726. /// <typeparam name="TDocument">The type of the document.</typeparam>
  727. public sealed class UpdateDefinitionBuilder<TDocument>
  728. {
  729. /// <summary>
  730. /// Creates an add to set operator.
  731. /// </summary>
  732. /// <typeparam name="TItem">The type of the item.</typeparam>
  733. /// <param name="field">The field.</param>
  734. /// <param name="value">The value.</param>
  735. /// <returns>An add to set operator.</returns>
  736. public UpdateDefinition<TDocument> AddToSet<TItem>(FieldDefinition<TDocument> field, TItem value)
  737. {
  738. return new AddToSetUpdateDefinition<TDocument, TItem>(
  739. field,
  740. new[] { value });
  741. }
  742. /// <summary>
  743. /// Creates an add to set operator.
  744. /// </summary>
  745. /// <typeparam name="TItem">The type of the item.</typeparam>
  746. /// <param name="field">The field.</param>
  747. /// <param name="value">The value.</param>
  748. /// <returns>An add to set operator.</returns>
  749. public UpdateDefinition<TDocument> AddToSet<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, TItem value)
  750. {
  751. return AddToSet<TItem>(new ExpressionFieldDefinition<TDocument>(field), value);
  752. }
  753. /// <summary>
  754. /// Creates an add to set operator.
  755. /// </summary>
  756. /// <typeparam name="TItem">The type of the item.</typeparam>
  757. /// <param name="field">The field.</param>
  758. /// <param name="values">The values.</param>
  759. /// <returns>An add to set operator.</returns>
  760. public UpdateDefinition<TDocument> AddToSetEach<TItem>(FieldDefinition<TDocument> field, IEnumerable<TItem> values)
  761. {
  762. return new AddToSetUpdateDefinition<TDocument, TItem>(field, values);
  763. }
  764. /// <summary>
  765. /// Creates an add to set operator.
  766. /// </summary>
  767. /// <typeparam name="TItem">The type of the item.</typeparam>
  768. /// <param name="field">The field.</param>
  769. /// <param name="values">The values.</param>
  770. /// <returns>An add to set operator.</returns>
  771. public UpdateDefinition<TDocument> AddToSetEach<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, IEnumerable<TItem> values)
  772. {
  773. return AddToSetEach(new ExpressionFieldDefinition<TDocument>(field), values);
  774. }
  775. /// <summary>
  776. /// Creates a bitwise and operator.
  777. /// </summary>
  778. /// <typeparam name="TField">The type of the field.</typeparam>
  779. /// <param name="field">The field.</param>
  780. /// <param name="value">The value.</param>
  781. /// <returns>A bitwise and operator.</returns>
  782. public UpdateDefinition<TDocument> BitwiseAnd<TField>(FieldDefinition<TDocument, TField> field, TField value)
  783. {
  784. return new BitwiseOperatorUpdateDefinition<TDocument, TField>("and", field, value);
  785. }
  786. /// <summary>
  787. /// Creates a bitwise and operator.
  788. /// </summary>
  789. /// <typeparam name="TField">The type of the field.</typeparam>
  790. /// <param name="field">The field.</param>
  791. /// <param name="value">The value.</param>
  792. /// <returns>A bitwise and operator.</returns>
  793. public UpdateDefinition<TDocument> BitwiseAnd<TField>(Expression<Func<TDocument, TField>> field, TField value)
  794. {
  795. return BitwiseAnd(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  796. }
  797. /// <summary>
  798. /// Creates a bitwise or operator.
  799. /// </summary>
  800. /// <typeparam name="TField">The type of the field.</typeparam>
  801. /// <param name="field">The field.</param>
  802. /// <param name="value">The value.</param>
  803. /// <returns>A bitwise or operator.</returns>
  804. public UpdateDefinition<TDocument> BitwiseOr<TField>(FieldDefinition<TDocument, TField> field, TField value)
  805. {
  806. return new BitwiseOperatorUpdateDefinition<TDocument, TField>("or", field, value);
  807. }
  808. /// <summary>
  809. /// Creates a bitwise or operator.
  810. /// </summary>
  811. /// <typeparam name="TField">The type of the field.</typeparam>
  812. /// <param name="field">The field.</param>
  813. /// <param name="value">The value.</param>
  814. /// <returns>A bitwise or operator.</returns>
  815. public UpdateDefinition<TDocument> BitwiseOr<TField>(Expression<Func<TDocument, TField>> field, TField value)
  816. {
  817. return BitwiseOr(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  818. }
  819. /// <summary>
  820. /// Creates a bitwise xor operator.
  821. /// </summary>
  822. /// <typeparam name="TField">The type of the field.</typeparam>
  823. /// <param name="field">The field.</param>
  824. /// <param name="value">The value.</param>
  825. /// <returns>A bitwise xor operator.</returns>
  826. public UpdateDefinition<TDocument> BitwiseXor<TField>(FieldDefinition<TDocument, TField> field, TField value)
  827. {
  828. return new BitwiseOperatorUpdateDefinition<TDocument, TField>("xor", field, value);
  829. }
  830. /// <summary>
  831. /// Creates a bitwise xor operator.
  832. /// </summary>
  833. /// <typeparam name="TField">The type of the field.</typeparam>
  834. /// <param name="field">The field.</param>
  835. /// <param name="value">The value.</param>
  836. /// <returns>A bitwise xor operator.</returns>
  837. public UpdateDefinition<TDocument> BitwiseXor<TField>(Expression<Func<TDocument, TField>> field, TField value)
  838. {
  839. return BitwiseXor(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  840. }
  841. /// <summary>
  842. /// Creates a combined update.
  843. /// </summary>
  844. /// <param name="updates">The updates.</param>
  845. /// <returns>A combined update.</returns>
  846. public UpdateDefinition<TDocument> Combine(params UpdateDefinition<TDocument>[] updates)
  847. {
  848. return Combine((IEnumerable<UpdateDefinition<TDocument>>)updates);
  849. }
  850. /// <summary>
  851. /// Creates a combined update.
  852. /// </summary>
  853. /// <param name="updates">The updates.</param>
  854. /// <returns>A combined update.</returns>
  855. public UpdateDefinition<TDocument> Combine(IEnumerable<UpdateDefinition<TDocument>> updates)
  856. {
  857. return new CombinedUpdateDefinition<TDocument>(updates);
  858. }
  859. /// <summary>
  860. /// Creates a current date operator.
  861. /// </summary>
  862. /// <param name="field">The field.</param>
  863. /// <param name="type">The type.</param>
  864. /// <returns>A current date operator.</returns>
  865. public UpdateDefinition<TDocument> CurrentDate(FieldDefinition<TDocument> field, UpdateDefinitionCurrentDateType? type = null)
  866. {
  867. BsonValue value;
  868. if (type.HasValue)
  869. {
  870. switch (type.Value)
  871. {
  872. case UpdateDefinitionCurrentDateType.Date:
  873. value = new BsonDocument("$type", "date");
  874. break;
  875. case UpdateDefinitionCurrentDateType.Timestamp:
  876. value = new BsonDocument("$type", "timestamp");
  877. break;
  878. default:
  879. throw new InvalidOperationException("Unknown value for " + typeof(UpdateDefinitionCurrentDateType));
  880. }
  881. }
  882. else
  883. {
  884. value = true;
  885. }
  886. return new OperatorUpdateDefinition<TDocument>("$currentDate", field, value);
  887. }
  888. /// <summary>
  889. /// Creates a current date operator.
  890. /// </summary>
  891. /// <param name="field">The field.</param>
  892. /// <param name="type">The type.</param>
  893. /// <returns>A current date operator.</returns>
  894. public UpdateDefinition<TDocument> CurrentDate(Expression<Func<TDocument, object>> field, UpdateDefinitionCurrentDateType? type = null)
  895. {
  896. return CurrentDate(new ExpressionFieldDefinition<TDocument>(field), type);
  897. }
  898. /// <summary>
  899. /// Creates an increment operator.
  900. /// </summary>
  901. /// <typeparam name="TField">The type of the field.</typeparam>
  902. /// <param name="field">The field.</param>
  903. /// <param name="value">The value.</param>
  904. /// <returns>An increment operator.</returns>
  905. public UpdateDefinition<TDocument> Inc<TField>(FieldDefinition<TDocument, TField> field, TField value)
  906. {
  907. return new OperatorUpdateDefinition<TDocument, TField>("$inc", field, value);
  908. }
  909. /// <summary>
  910. /// Creates an increment operator.
  911. /// </summary>
  912. /// <typeparam name="TField">The type of the field.</typeparam>
  913. /// <param name="field">The field.</param>
  914. /// <param name="value">The value.</param>
  915. /// <returns>An increment operator.</returns>
  916. public UpdateDefinition<TDocument> Inc<TField>(Expression<Func<TDocument, TField>> field, TField value)
  917. {
  918. return Inc(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  919. }
  920. /// <summary>
  921. /// Creates a max operator.
  922. /// </summary>
  923. /// <typeparam name="TField">The type of the field.</typeparam>
  924. /// <param name="field">The field.</param>
  925. /// <param name="value">The value.</param>
  926. /// <returns>A max operator.</returns>
  927. public UpdateDefinition<TDocument> Max<TField>(FieldDefinition<TDocument, TField> field, TField value)
  928. {
  929. return new OperatorUpdateDefinition<TDocument, TField>("$max", field, value);
  930. }
  931. /// <summary>
  932. /// Creates a max operator.
  933. /// </summary>
  934. /// <typeparam name="TField">The type of the field.</typeparam>
  935. /// <param name="field">The field.</param>
  936. /// <param name="value">The value.</param>
  937. /// <returns>A max operator.</returns>
  938. public UpdateDefinition<TDocument> Max<TField>(Expression<Func<TDocument, TField>> field, TField value)
  939. {
  940. return Max(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  941. }
  942. /// <summary>
  943. /// Creates a min operator.
  944. /// </summary>
  945. /// <typeparam name="TField">The type of the field.</typeparam>
  946. /// <param name="field">The field.</param>
  947. /// <param name="value">The value.</param>
  948. /// <returns>A min operator.</returns>
  949. public UpdateDefinition<TDocument> Min<TField>(FieldDefinition<TDocument, TField> field, TField value)
  950. {
  951. return new OperatorUpdateDefinition<TDocument, TField>("$min", field, value);
  952. }
  953. /// <summary>
  954. /// Creates a min operator.
  955. /// </summary>
  956. /// <typeparam name="TField">The type of the field.</typeparam>
  957. /// <param name="field">The field.</param>
  958. /// <param name="value">The value.</param>
  959. /// <returns>A min operator.</returns>
  960. public UpdateDefinition<TDocument> Min<TField>(Expression<Func<TDocument, TField>> field, TField value)
  961. {
  962. return Min(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  963. }
  964. /// <summary>
  965. /// Creates a multiply operator.
  966. /// </summary>
  967. /// <typeparam name="TField">The type of the field.</typeparam>
  968. /// <param name="field">The field.</param>
  969. /// <param name="value">The value.</param>
  970. /// <returns>A multiply operator.</returns>
  971. public UpdateDefinition<TDocument> Mul<TField>(FieldDefinition<TDocument, TField> field, TField value)
  972. {
  973. return new OperatorUpdateDefinition<TDocument, TField>("$mul", field, value);
  974. }
  975. /// <summary>
  976. /// Creates a multiply operator.
  977. /// </summary>
  978. /// <typeparam name="TField">The type of the field.</typeparam>
  979. /// <param name="field">The field.</param>
  980. /// <param name="value">The value.</param>
  981. /// <returns>A multiply operator.</returns>
  982. public UpdateDefinition<TDocument> Mul<TField>(Expression<Func<TDocument, TField>> field, TField value)
  983. {
  984. return Mul(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  985. }
  986. /// <summary>
  987. /// Creates a pop operator.
  988. /// </summary>
  989. /// <param name="field">The field.</param>
  990. /// <returns>A pop operator.</returns>
  991. public UpdateDefinition<TDocument> PopFirst(FieldDefinition<TDocument> field)
  992. {
  993. return new OperatorUpdateDefinition<TDocument>("$pop", field, -1);
  994. }
  995. /// <summary>
  996. /// Creates a pop first operator.
  997. /// </summary>
  998. /// <param name="field">The field.</param>
  999. /// <returns>A pop first operator.</returns>
  1000. public UpdateDefinition<TDocument> PopFirst(Expression<Func<TDocument, object>> field)
  1001. {
  1002. return PopFirst(new ExpressionFieldDefinition<TDocument>(field));
  1003. }
  1004. /// <summary>
  1005. /// Creates a pop operator.
  1006. /// </summary>
  1007. /// <param name="field">The field.</param>
  1008. /// <returns>A pop operator.</returns>
  1009. public UpdateDefinition<TDocument> PopLast(FieldDefinition<TDocument> field)
  1010. {
  1011. return new OperatorUpdateDefinition<TDocument>("$pop", field, 1);
  1012. }
  1013. /// <summary>
  1014. /// Creates a pop first operator.
  1015. /// </summary>
  1016. /// <param name="field">The field.</param>
  1017. /// <returns>A pop first operator.</returns>
  1018. public UpdateDefinition<TDocument> PopLast(Expression<Func<TDocument, object>> field)
  1019. {
  1020. return PopLast(new ExpressionFieldDefinition<TDocument>(field));
  1021. }
  1022. /// <summary>
  1023. /// Creates a pull operator.
  1024. /// </summary>
  1025. /// <typeparam name="TItem">The type of the item.</typeparam>
  1026. /// <param name="field">The field.</param>
  1027. /// <param name="value">The value.</param>
  1028. /// <returns>A pull operator.</returns>
  1029. public UpdateDefinition<TDocument> Pull<TItem>(FieldDefinition<TDocument> field, TItem value)
  1030. {
  1031. return new PullUpdateDefinition<TDocument, TItem>(field, new[] { value });
  1032. }
  1033. /// <summary>
  1034. /// Creates a pull operator.
  1035. /// </summary>
  1036. /// <typeparam name="TItem">The type of the item.</typeparam>
  1037. /// <param name="field">The field.</param>
  1038. /// <param name="value">The value.</param>
  1039. /// <returns>A pull operator.</returns>
  1040. public UpdateDefinition<TDocument> Pull<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, TItem value)
  1041. {
  1042. return Pull<TItem>(new ExpressionFieldDefinition<TDocument>(field), value);
  1043. }
  1044. /// <summary>
  1045. /// Creates a pull operator.
  1046. /// </summary>
  1047. /// <typeparam name="TItem">The type of the item.</typeparam>
  1048. /// <param name="field">The field.</param>
  1049. /// <param name="values">The values.</param>
  1050. /// <returns>A pull operator.</returns>
  1051. public UpdateDefinition<TDocument> PullAll<TItem>(FieldDefinition<TDocument> field, IEnumerable<TItem> values)
  1052. {
  1053. return new PullUpdateDefinition<TDocument, TItem>(field, values);
  1054. }
  1055. /// <summary>
  1056. /// Creates a pull operator.
  1057. /// </summary>
  1058. /// <typeparam name="TItem">The type of the item.</typeparam>
  1059. /// <param name="field">The field.</param>
  1060. /// <param name="values">The values.</param>
  1061. /// <returns>A pull operator.</returns>
  1062. public UpdateDefinition<TDocument> PullAll<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, IEnumerable<TItem> values)
  1063. {
  1064. return PullAll(new ExpressionFieldDefinition<TDocument>(field), values);
  1065. }
  1066. /// <summary>
  1067. /// Creates a pull operator.
  1068. /// </summary>
  1069. /// <typeparam name="TItem">The type of the item.</typeparam>
  1070. /// <param name="field">The field.</param>
  1071. /// <param name="filter">The filter.</param>
  1072. /// <returns>A pull operator.</returns>
  1073. public UpdateDefinition<TDocument> PullFilter<TItem>(FieldDefinition<TDocument> field, FilterDefinition<TItem> filter)
  1074. {
  1075. return new PullUpdateDefinition<TDocument, TItem>(field, filter);
  1076. }
  1077. /// <summary>
  1078. /// Creates a pull operator.
  1079. /// </summary>
  1080. /// <typeparam name="TItem">The type of the item.</typeparam>
  1081. /// <param name="field">The field.</param>
  1082. /// <param name="filter">The filter.</param>
  1083. /// <returns>A pull operator.</returns>
  1084. public UpdateDefinition<TDocument> PullFilter<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, FilterDefinition<TItem> filter)
  1085. {
  1086. return PullFilter(new ExpressionFieldDefinition<TDocument>(field), filter);
  1087. }
  1088. /// <summary>
  1089. /// Creates a pull operator.
  1090. /// </summary>
  1091. /// <typeparam name="TItem">The type of the item.</typeparam>
  1092. /// <param name="field">The field.</param>
  1093. /// <param name="filter">The filter.</param>
  1094. /// <returns>A pull operator.</returns>
  1095. public UpdateDefinition<TDocument> PullFilter<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, Expression<Func<TItem, bool>> filter)
  1096. {
  1097. return PullFilter(new ExpressionFieldDefinition<TDocument>(field), new ExpressionFilterDefinition<TItem>(filter));
  1098. }
  1099. /// <summary>
  1100. /// Creates a push operator.
  1101. /// </summary>
  1102. /// <typeparam name="TItem">The type of the item.</typeparam>
  1103. /// <param name="field">The field.</param>
  1104. /// <param name="value">The value.</param>
  1105. /// <returns>A push operator.</returns>
  1106. public UpdateDefinition<TDocument> Push<TItem>(FieldDefinition<TDocument> field, TItem value)
  1107. {
  1108. return new PushUpdateDefinition<TDocument, TItem>(field, new[] { value });
  1109. }
  1110. /// <summary>
  1111. /// Creates a push operator.
  1112. /// </summary>
  1113. /// <typeparam name="TItem">The type of the item.</typeparam>
  1114. /// <param name="field">The field.</param>
  1115. /// <param name="value">The value.</param>
  1116. /// <returns>A push operator.</returns>
  1117. public UpdateDefinition<TDocument> Push<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, TItem value)
  1118. {
  1119. return Push(new ExpressionFieldDefinition<TDocument>(field), value);
  1120. }
  1121. /// <summary>
  1122. /// Creates a push operator.
  1123. /// </summary>
  1124. /// <typeparam name="TItem">The type of the item.</typeparam>
  1125. /// <param name="field">The field.</param>
  1126. /// <param name="values">The values.</param>
  1127. /// <param name="slice">The slice.</param>
  1128. /// <param name="position">The position.</param>
  1129. /// <param name="sort">The sort.</param>
  1130. /// <returns>A push operator.</returns>
  1131. public UpdateDefinition<TDocument> PushEach<TItem>(FieldDefinition<TDocument> field, IEnumerable<TItem> values, int? slice = null, int? position = null, SortDefinition<TItem> sort = null)
  1132. {
  1133. return new PushUpdateDefinition<TDocument, TItem>(field, values, slice, position, sort);
  1134. }
  1135. /// <summary>
  1136. /// Creates a push operator.
  1137. /// </summary>
  1138. /// <typeparam name="TItem">The type of the item.</typeparam>
  1139. /// <param name="field">The field.</param>
  1140. /// <param name="values">The values.</param>
  1141. /// <param name="slice">The slice.</param>
  1142. /// <param name="position">The position.</param>
  1143. /// <param name="sort">The sort.</param>
  1144. /// <returns>A push operator.</returns>
  1145. public UpdateDefinition<TDocument> PushEach<TItem>(Expression<Func<TDocument, IEnumerable<TItem>>> field, IEnumerable<TItem> values, int? slice = null, int? position = null, SortDefinition<TItem> sort = null)
  1146. {
  1147. return PushEach(new ExpressionFieldDefinition<TDocument>(field), values, slice, position, sort);
  1148. }
  1149. /// <summary>
  1150. /// Creates a field renaming operator.
  1151. /// </summary>
  1152. /// <param name="field">The field.</param>
  1153. /// <param name="newName">The new name.</param>
  1154. /// <returns>A field rename operator.</returns>
  1155. public UpdateDefinition<TDocument> Rename(FieldDefinition<TDocument> field, string newName)
  1156. {
  1157. return new OperatorUpdateDefinition<TDocument>("$rename", field, newName);
  1158. }
  1159. /// <summary>
  1160. /// Creates a field renaming operator.
  1161. /// </summary>
  1162. /// <param name="field">The field.</param>
  1163. /// <param name="newName">The new name.</param>
  1164. /// <returns>A field rename operator.</returns>
  1165. public UpdateDefinition<TDocument> Rename(Expression<Func<TDocument, object>> field, string newName)
  1166. {
  1167. return Rename(new ExpressionFieldDefinition<TDocument>(field), newName);
  1168. }
  1169. /// <summary>
  1170. /// Creates a set operator.
  1171. /// </summary>
  1172. /// <typeparam name="TField">The type of the field.</typeparam>
  1173. /// <param name="field">The field.</param>
  1174. /// <param name="value">The value.</param>
  1175. /// <returns>A set operator.</returns>
  1176. public UpdateDefinition<TDocument> Set<TField>(FieldDefinition<TDocument, TField> field, TField value)
  1177. {
  1178. return new OperatorUpdateDefinition<TDocument, TField>("$set", field, value);
  1179. }
  1180. /// <summary>
  1181. /// Creates a set operator.
  1182. /// </summary>
  1183. /// <typeparam name="TField">The type of the field.</typeparam>
  1184. /// <param name="field">The field.</param>
  1185. /// <param name="value">The value.</param>
  1186. /// <returns>A set operator.</returns>
  1187. public UpdateDefinition<TDocument> Set<TField>(Expression<Func<TDocument, TField>> field, TField value)
  1188. {
  1189. return Set(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  1190. }
  1191. /// <summary>
  1192. /// Creates a set on insert operator.
  1193. /// </summary>
  1194. /// <typeparam name="TField">The type of the field.</typeparam>
  1195. /// <param name="field">The field.</param>
  1196. /// <param name="value">The value.</param>
  1197. /// <returns>A set on insert operator.</returns>
  1198. public UpdateDefinition<TDocument> SetOnInsert<TField>(FieldDefinition<TDocument, TField> field, TField value)
  1199. {
  1200. return new OperatorUpdateDefinition<TDocument, TField>("$setOnInsert", field, value);
  1201. }
  1202. /// <summary>
  1203. /// Creates a set on insert operator.
  1204. /// </summary>
  1205. /// <typeparam name="TField">The type of the field.</typeparam>
  1206. /// <param name="field">The field.</param>
  1207. /// <param name="value">The value.</param>
  1208. /// <returns>A set on insert operator.</returns>
  1209. public UpdateDefinition<TDocument> SetOnInsert<TField>(Expression<Func<TDocument, TField>> field, TField value)
  1210. {
  1211. return SetOnInsert(new ExpressionFieldDefinition<TDocument, TField>(field), value);
  1212. }
  1213. /// <summary>
  1214. /// Creates an unset operator.
  1215. /// </summary>
  1216. /// <param name="field">The field.</param>
  1217. /// <returns>An unset operator.</returns>
  1218. public UpdateDefinition<TDocument> Unset(FieldDefinition<TDocument> field)
  1219. {
  1220. return new OperatorUpdateDefinition<TDocument>("$unset", field, 1);
  1221. }
  1222. /// <summary>
  1223. /// Creates an unset operator.
  1224. /// </summary>
  1225. /// <param name="field">The field.</param>
  1226. /// <returns>An unset operator.</returns>
  1227. public UpdateDefinition<TDocument> Unset(Expression<Func<TDocument, object>> field)
  1228. {
  1229. return Unset(new ExpressionFieldDefinition<TDocument>(field));
  1230. }
  1231. }
  1232. internal sealed class AddToSetUpdateDefinition<TDocument, TItem> : UpdateDefinition<TDocument>
  1233. {
  1234. private readonly FieldDefinition<TDocument> _field;
  1235. private readonly List<TItem> _values;
  1236. public AddToSetUpdateDefinition(FieldDefinition<TDocument> field, IEnumerable<TItem> values)
  1237. {
  1238. _field = Ensure.IsNotNull(field, nameof(field));
  1239. _values = Ensure.IsNotNull(values, nameof(values)).ToList();
  1240. }
  1241. public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
  1242. {
  1243. var renderedField = _field.Render(documentSerializer, serializerRegistry);
  1244. IBsonSerializer itemSerializer;
  1245. if (renderedField.FieldSerializer != null)
  1246. {
  1247. var arraySerializer = renderedField.FieldSerializer as IBsonArraySerializer;
  1248. BsonSerializationInfo itemSerializationInfo;
  1249. if (arraySerializer == null || !arraySerializer.TryGetItemSerializationInfo(out itemSerializationInfo))
  1250. {
  1251. var message = string.Format("The serializer for field '{0}' must implement IBsonArraySerializer and provide item serialization info.", renderedField.FieldName);
  1252. throw new InvalidOperationException(message);
  1253. }
  1254. itemSerializer = itemSerializationInfo.Serializer;
  1255. }
  1256. else
  1257. {
  1258. itemSerializer = serializerRegistry.GetSerializer<TItem>();
  1259. }
  1260. var document = new BsonDocument();
  1261. using (var bsonWriter = new BsonDocumentWriter(document))
  1262. {
  1263. var context = BsonSerializationContext.CreateRoot(bsonWriter);
  1264. bsonWriter.WriteStartDocument();
  1265. bsonWriter.WriteName("$addToSet");
  1266. bsonWriter.WriteStartDocument();
  1267. bsonWriter.WriteName(renderedField.FieldName);
  1268. if (_values.Count == 1)
  1269. {
  1270. itemSerializer.Serialize(context, _values[0]);
  1271. }
  1272. else
  1273. {
  1274. bsonWriter.WriteStartDocument();
  1275. bsonWriter.WriteName("$each");
  1276. bsonWriter.WriteStartArray();
  1277. foreach (var value in _values)
  1278. {
  1279. itemSerializer.Serialize(context, value);
  1280. }
  1281. bsonWriter.WriteEndArray();
  1282. bsonWriter.WriteEndDocument();
  1283. }
  1284. bsonWriter.WriteEndDocument();
  1285. bsonWriter.WriteEndDocument();
  1286. }
  1287. return document;
  1288. }
  1289. }
  1290. internal sealed class CombinedUpdateDefinition<TDocument> : UpdateDefinition<TDocument>
  1291. {
  1292. private readonly List<UpdateDefinition<TDocument>> _updates;
  1293. public CombinedUpdateDefinition(IEnumerable<UpdateDefinition<TDocument>> updates)
  1294. {
  1295. _updates = Ensure.IsNotNull(updates, nameof(updates)).ToList();
  1296. }
  1297. public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
  1298. {
  1299. var document = new BsonDocument();
  1300. foreach (var update in _updates)
  1301. {
  1302. var renderedUpdate = update.Render(documentSerializer, serializerRegistry);
  1303. foreach (var element in renderedUpdate.Elements)
  1304. {
  1305. BsonValue currentOperatorValue;
  1306. if (document.TryGetValue(element.Name, out currentOperatorValue))
  1307. {
  1308. // last one wins
  1309. document[element.Name] = ((BsonDocument)currentOperatorValue)
  1310. .Merge((BsonDocument)element.Value, overwriteExistingElements: true);
  1311. }
  1312. else
  1313. {
  1314. document.Add(element);
  1315. }
  1316. }
  1317. }
  1318. return document;
  1319. }
  1320. }
  1321. internal sealed class BitwiseOperatorUpdateDefinition<TDocument, TField> : UpdateDefinition<TDocument>
  1322. {
  1323. private readonly string _operatorName;
  1324. private readonly FieldDefinition<TDocument, TField> _field;
  1325. private readonly TField _value;
  1326. public BitwiseOperatorUpdateDefinition(string operatorName, FieldDefinition<TDocument, TField> field, TField value)
  1327. {
  1328. _operatorName = Ensure.IsNotNull(operatorName, nameof(operatorName));
  1329. _field = Ensure.IsNotNull(field, nameof(field));
  1330. _value = value;
  1331. }
  1332. public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
  1333. {
  1334. var renderedField = _field.Render(documentSerializer, serializerRegistry);
  1335. var document = new BsonDocument();
  1336. using (var bsonWriter = new BsonDocumentWriter(document))
  1337. {
  1338. var context = BsonSerializationContext.CreateRoot(bsonWriter);
  1339. bsonWriter.WriteStartDocument();
  1340. bsonWriter.WriteName("$bit");
  1341. bsonWriter.WriteStartDocument();
  1342. bsonWriter.WriteName(renderedField.FieldName);
  1343. bsonWriter.WriteStartDocument();
  1344. bsonWriter.WriteName(_operatorName);
  1345. renderedField.ValueSerializer.Serialize(context, _value);
  1346. bsonWriter.WriteEndDocument();
  1347. bsonWriter.WriteEndDocument();
  1348. bsonWriter.WriteEndDocument();
  1349. }
  1350. return document;
  1351. }
  1352. }
  1353. internal sealed class OperatorUpdateDefinition<TDocument> : UpdateDefinition<TDocument>
  1354. {
  1355. private readonly string _operatorName;
  1356. private readonly FieldDefinition<TDocument> _field;
  1357. private readonly BsonValue _value;
  1358. public OperatorUpdateDefinition(string operatorName, FieldDefinition<TDocument> field, BsonValue value)
  1359. {
  1360. _operatorName = Ensure.IsNotNull(operatorName, nameof(operatorName));
  1361. _field = Ensure.IsNotNull(field, nameof(field));
  1362. _value = value;
  1363. }
  1364. public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
  1365. {
  1366. var renderedField = _field.Render(documentSerializer, serializerRegistry);
  1367. return new BsonDocument(_operatorName, new BsonDocument(renderedField.FieldName, _value));
  1368. }
  1369. }
  1370. internal sealed class OperatorUpdateDefinition<TDocument, TField> : UpdateDefinition<TDocument>
  1371. {
  1372. private readonly string _operatorName;
  1373. private readonly FieldDefinition<TDocument, TField> _field;
  1374. private readonly TField _value;
  1375. public OperatorUpdateDefinition(string operatorName, FieldDefinition<TDocument, TField> field, TField value)
  1376. {
  1377. _operatorName = Ensure.IsNotNull(operatorName, nameof(operatorName));
  1378. _field = Ensure.IsNotNull(field, nameof(field));
  1379. _value = value;
  1380. }
  1381. public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
  1382. {
  1383. var renderedField = _field.Render(documentSerializer, serializerRegistry);
  1384. var document = new BsonDocument();
  1385. using (var bsonWriter = new BsonDocumentWriter(document))
  1386. {
  1387. var context = BsonSerializationContext.CreateRoot(bsonWriter);
  1388. bsonWriter.WriteStartDocument();
  1389. bsonWriter.WriteName(_operatorName);
  1390. bsonWriter.WriteStartDocument();
  1391. bsonWriter.WriteName(renderedField.FieldName);
  1392. renderedField.ValueSerializer.Serialize(context, _value);
  1393. bsonWriter.WriteEndDocument();
  1394. bsonWriter.WriteEndDocument();
  1395. }
  1396. return document;
  1397. }
  1398. }
  1399. internal sealed class PullUpdateDefinition<TDocument, TItem> : UpdateDefinition<TDocument>
  1400. {
  1401. private readonly FieldDefinition<TDocument> _field;
  1402. private readonly FilterDefinition<TItem> _filter;
  1403. private readonly List<TItem> _values;
  1404. public PullUpdateDefinition(FieldDefinition<TDocument> field, FilterDefinition<TItem> filter)
  1405. {
  1406. _field = Ensure.IsNotNull(field, nameof(field));
  1407. _filter = Ensure.IsNotNull(filter, nameof(filter));
  1408. }
  1409. public PullUpdateDefinition(FieldDefinition<TDocument> field, IEnumerable<TItem> values)
  1410. {
  1411. _field = Ensure.IsNotNull(field, nameof(field));
  1412. _values = Ensure.IsNotNull(values, nameof(values)).ToList();
  1413. }
  1414. public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
  1415. {
  1416. var renderedField = _field.Render(documentSerializer, serializerRegistry);
  1417. IBsonSerializer itemSerializer;
  1418. if (renderedField.FieldSerializer != null)
  1419. {
  1420. var arraySerializer = renderedField.FieldSerializer as IBsonArraySerializer;
  1421. BsonSerializationInfo itemSerializationInfo;
  1422. if (arraySerializer == null || !arraySerializer.TryGetItemSerializationInfo(out itemSerializationInfo))
  1423. {
  1424. var message = string.Format("The serializer for field '{0}' must implement IBsonArraySerializer and provide item serialization info.", renderedField.FieldName);
  1425. throw new InvalidOperationException(message);
  1426. }
  1427. itemSerializer = itemSerializationInfo.Serializer;
  1428. }
  1429. else
  1430. {
  1431. itemSerializer = serializerRegistry.GetSerializer<TItem>();
  1432. }
  1433. if (_filter != null)
  1434. {
  1435. var renderedFilter = _filter.Render((IBsonSerializer<TItem>)itemSerializer, serializerRegistry);
  1436. return new BsonDocument("$pull", new BsonDocument(renderedField.FieldName, renderedFilter));
  1437. }
  1438. else
  1439. {
  1440. var document = new BsonDocument();
  1441. using (var bsonWriter = new BsonDocumentWriter(document))
  1442. {
  1443. var context = BsonSerializationContext.CreateRoot(bsonWriter);
  1444. bsonWriter.WriteStartDocument();
  1445. bsonWriter.WriteName(_values.Count == 1 ? "$pull" : "$pullAll");
  1446. bsonWriter.WriteStartDocument();
  1447. bsonWriter.WriteName(renderedField.FieldName);
  1448. if (_values.Count == 1)
  1449. {
  1450. itemSerializer.Serialize(context, _values[0]);
  1451. }
  1452. else
  1453. {
  1454. bsonWriter.WriteStartArray();
  1455. foreach (var value in _values)
  1456. {
  1457. itemSerializer.Serialize(context, value);
  1458. }
  1459. bsonWriter.WriteEndArray();
  1460. }
  1461. bsonWriter.WriteEndDocument();
  1462. bsonWriter.WriteEndDocument();
  1463. }
  1464. return document;
  1465. }
  1466. }
  1467. }
  1468. internal sealed class PushUpdateDefinition<TDocument, TItem> : UpdateDefinition<TDocument>
  1469. {
  1470. private readonly FieldDefinition<TDocument> _field;
  1471. private readonly int? _position;
  1472. private readonly int? _slice;
  1473. private SortDefinition<TItem> _sort;
  1474. private readonly List<TItem> _values;
  1475. public PushUpdateDefinition(FieldDefinition<TDocument> field, IEnumerable<TItem> values, int? slice = null, int? position = null, SortDefinition<TItem> sort = null)
  1476. {
  1477. _field = Ensure.IsNotNull(field, nameof(field));
  1478. _values = Ensure.IsNotNull(values, nameof(values)).ToList();
  1479. _slice = slice;
  1480. _position = position;
  1481. _sort = sort;
  1482. }
  1483. public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
  1484. {
  1485. var renderedField = _field.Render(documentSerializer, serializerRegistry);
  1486. IBsonSerializer itemSerializer;
  1487. if (renderedField.FieldSerializer != null)
  1488. {
  1489. var arraySerializer = renderedField.FieldSerializer as IBsonArraySerializer;
  1490. BsonSerializationInfo itemSerializationInfo;
  1491. if (arraySerializer == null || !arraySerializer.TryGetItemSerializationInfo(out itemSerializationInfo))
  1492. {
  1493. var message = string.Format("The serializer for field '{0}' must implement IBsonArraySerializer and provide item serialization info.", renderedField.FieldName);
  1494. throw new InvalidOperationException(message);
  1495. }
  1496. itemSerializer = itemSerializationInfo.Serializer;
  1497. }
  1498. else
  1499. {
  1500. itemSerializer = serializerRegistry.GetSerializer<TItem>();
  1501. }
  1502. var document = new BsonDocument();
  1503. using (var bsonWriter = new BsonDocumentWriter(document))
  1504. {
  1505. var context = BsonSerializationContext.CreateRoot(bsonWriter);
  1506. bsonWriter.WriteStartDocument();
  1507. bsonWriter.WriteName("$push");
  1508. bsonWriter.WriteStartDocument();
  1509. bsonWriter.WriteName(renderedField.FieldName);
  1510. if (!_slice.HasValue && !_position.HasValue && _sort == null && _values.Count == 1)
  1511. {
  1512. itemSerializer.Serialize(context, _values[0]);
  1513. }
  1514. else
  1515. {
  1516. bsonWriter.WriteStartDocument();
  1517. bsonWriter.WriteName("$each");
  1518. bsonWriter.WriteStartArray();
  1519. foreach (var value in _values)
  1520. {
  1521. itemSerializer.Serialize(context, value);
  1522. }
  1523. bsonWriter.WriteEndArray();
  1524. if (_slice.HasValue)
  1525. {
  1526. bsonWriter.WriteName("$slice");
  1527. bsonWriter.WriteInt32(_slice.Value);
  1528. }
  1529. if (_position.HasValue)
  1530. {
  1531. bsonWriter.WriteName("$position");
  1532. bsonWriter.WriteInt32(_position.Value);
  1533. }
  1534. bsonWriter.WriteEndDocument();
  1535. }
  1536. bsonWriter.WriteEndDocument();
  1537. bsonWriter.WriteEndDocument();
  1538. }
  1539. if (_sort != null)
  1540. {
  1541. document["$push"][renderedField.FieldName]["$sort"] = _sort.Render((IBsonSerializer<TItem>)itemSerializer, serializerRegistry);
  1542. }
  1543. return document;
  1544. }
  1545. }
  1546. }