1 /**
2 	MongoDB CRUD API definitions.
3 
4 	Copyright: © 2022 Jan Jurzitza
5 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
6 	Authors: Jan Jurzitza
7 */
8 module vibe.db.mongo.impl.crud;
9 
10 import core.time;
11 
12 import vibe.db.mongo.connection : MongoException;
13 import vibe.db.mongo.collection;
14 import vibe.data.bson;
15 
16 import std.typecons;
17 
18 @safe:
19 
20 deprecated("Use UpdateOptions instead")
21 enum UpdateFlags {
22 	none         = 0,    /// Normal update of a single document.
23 	upsert       = 1<<0, /// Creates a document if none exists.
24 	multiUpdate  = 1<<1, /// Updates all matching documents.
25 
26 	None = none, /// Deprecated compatibility alias
27 	Upsert = upsert, /// Deprecated compatibility alias
28 	MultiUpdate = multiUpdate /// Deprecated compatibility alias
29 }
30 
31 deprecated("Use InsertOneOptions or InsertManyOptions instead")
32 enum InsertFlags {
33 	none             = 0,    /// Normal insert.
34 	continueOnError  = 1<<0, /// For multiple inserted documents, continues inserting further documents after a failure.
35 
36 	None = none, /// Deprecated compatibility alias
37 	ContinueOnError = continueOnError /// Deprecated compatibility alias
38 }
39 
40 deprecated("Use FindOptions instead")
41 enum QueryFlags {
42 	none             = 0,    /// Normal query
43 	tailableCursor   = 1<<1, ///
44 	slaveOk          = 1<<2, ///
45 	oplogReplay      = 1<<3, ///
46 	noCursorTimeout  = 1<<4, ///
47 	awaitData        = 1<<5, ///
48 	exhaust          = 1<<6, ///
49 	partial          = 1<<7, ///
50 
51 	None = none, /// Deprecated compatibility alias
52 	TailableCursor = tailableCursor, /// Deprecated compatibility alias
53 	SlaveOk = slaveOk, /// Deprecated compatibility alias
54 	OplogReplay = oplogReplay, /// Deprecated compatibility alias
55 	NoCursorTimeout = noCursorTimeout, /// Deprecated compatibility alias
56 	AwaitData = awaitData, /// Deprecated compatibility alias
57 	Exhaust = exhaust, /// Deprecated compatibility alias
58 	Partial = partial /// Deprecated compatibility alias
59 }
60 
61 deprecated("Use DeleteOptions instead")
62 enum DeleteFlags {
63 	none          = 0,
64 	singleRemove  = 1<<0,
65 
66 	None = none, /// Deprecated compatibility alias
67 	SingleRemove = singleRemove /// Deprecated compatibility alias
68 }
69 
70 /**
71 	See_Also: $(LINK https://docs.mongodb.com/manual/reference/command/find/)
72 
73 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#id16)
74 */
75 struct FindOptions
76 {
77 	/**
78 		Enables writing to temporary files on the server. When set to true, the server
79 		can write temporary data to disk while executing the find operation.
80 
81 		This option is only supported by servers >= 4.4.
82 	*/
83 	@embedNullable @errorBefore(WireVersion.v44)
84 	Nullable!bool allowDiskUse;
85 
86 	/**
87 		Get partial results from a mongos if some shards are down (instead of throwing an error).
88 	*/
89 	@embedNullable
90 	Nullable!bool allowPartialResults;
91 
92 	/**
93 		The number of documents to return per batch.
94 	*/
95 	@embedNullable
96 	Nullable!int batchSize;
97 
98 	/**
99 		Determines whether to close the cursor after the first batch.
100 
101 		Set automatically if limit < 0 || batchSize < 0.
102 	*/
103 	@embedNullable
104 	package Nullable!bool singleBatch;
105 
106 	/**
107 		Collation allows users to specify language-specific rules for string
108 		comparison, such as rules for letter-case and accent marks.
109 	*/
110 	@embedNullable @errorBefore(WireVersion.v34)
111 	Nullable!Collation collation;
112 
113 	/**
114 		Users can specify an arbitrary string to help trace the operation
115 		through the database profiler, currentOp, and logs.
116 	*/
117 	@embedNullable
118 	Nullable!string comment;
119 
120 	/**
121 		Indicates the type of cursor to use. This value includes both
122 		the tailable and awaitData options.
123 	*/
124 	@ignore CursorType cursorType;
125 
126 	/**
127 		The index to use. Specify either the index name as a string or the index
128 		key pattern.
129 
130 		If specified, then the query system will only consider plans using the
131 		hinted index.
132 	*/
133 	@embedNullable
134 	Nullable!Bson hint;
135 
136 	/**
137 		The maximum number of documents to return.
138 
139 		A negative limit only returns a single batch of results.
140 	*/
141 	@embedNullable
142 	Nullable!long limit;
143 
144 	/**
145 		The exclusive upper bound for a specific index.
146 	*/
147 	@embedNullable
148 	Nullable!Bson max;
149 
150 	/**
151 		The maximum amount of time for the server to wait on new documents to
152 		satisfy a tailable cursor query. This only applies to a TAILABLE_AWAIT
153 		cursor. When the cursor is not a TAILABLE_AWAIT cursor, this option is
154 		ignored.
155 
156 		Note: This option is specified as "maxTimeMS" in the getMore command and
157 		not provided as part of the initial find command.
158 	*/
159 	@embedNullable @since(WireVersion.v32)
160 	Nullable!long maxAwaitTimeMS;
161 
162 	/// ditto
163 	void maxAwaitTime(Duration d)
164 	@safe {
165 		maxAwaitTimeMS = cast(long)d.total!"msecs";
166 	}
167 
168 	/**
169 		Maximum number of documents or index keys to scan when executing the query.
170 	*/
171 	@embedNullable @deprecatedSince(WireVersion.v40)
172 	Nullable!long maxScan;
173 
174 	/**
175 		The maximum amount of time to allow the query to run.
176 	*/
177 	@embedNullable
178 	Nullable!long maxTimeMS;
179 
180 	/// ditto
181 	void maxTime(Duration d)
182 	@safe {
183 		maxTimeMS = cast(long)d.total!"msecs";
184 	}
185 
186 	/**
187 		The exclusive lower bound for a specific index.
188 	*/
189 	@embedNullable
190 	Nullable!Bson min;
191 
192 	/**
193 		The server normally times out idle cursors after an inactivity period
194 		(10 minutes) to prevent excess memory use. Set this option to prevent
195 		that.
196 	*/
197 	@embedNullable
198 	Nullable!bool noCursorTimeout;
199 
200 	/**
201 		Enables optimization when querying the oplog for a range of ts values.
202 
203 		Note: this option is intended for internal replication use only.
204 	*/
205 	@embedNullable @deprecatedSince(WireVersion.v44)
206 	Nullable!bool oplogReplay;
207 
208 	/**
209 		Limits the fields to return for all matching documents.
210 	*/
211 	@embedNullable
212 	Nullable!Bson projection;
213 
214 	/**
215 		If true, returns only the index keys in the resulting documents.
216 	*/
217 	@embedNullable
218 	Nullable!bool returnKey;
219 
220 	/**
221 		Determines whether to return the record identifier for each document. If
222 		true, adds a field $recordId to the returned documents.
223 	*/
224 	@embedNullable
225 	Nullable!bool showRecordId;
226 
227 	/**
228 		The number of documents to skip before returning.
229 	*/
230 	@embedNullable
231 	Nullable!long skip;
232 
233 	/**
234 		Prevents the cursor from returning a document more than once because of
235 		an intervening write operation.
236 	*/
237 	@embedNullable @deprecatedSince(WireVersion.v40)
238 	Nullable!bool snapshot;
239 
240 	/**
241 		The order in which to return matching documents.
242 	*/
243 	@embedNullable
244 	Nullable!Bson sort;
245 
246 	/**
247 		If true, when an insert fails, return without performing the remaining
248 		writes. If false, when a write fails, continue with the remaining writes,
249 		if any.
250 
251 		Defaults to true.
252 	*/
253 	@embedNullable
254 	Nullable!bool ordered;
255 
256 	/**
257 		Specifies the read concern. Only compatible with a write stage. (e.g.
258 		`$out`, `$merge`)
259 
260 		Aggregate commands do not support the $(D ReadConcern.Level.linearizable)
261 		level.
262 
263 		Standards: $(LINK https://github.com/mongodb/specifications/blob/7745234f93039a83ae42589a6c0cdbefcffa32fa/source/read-write-concern/read-write-concern.rst)
264 	*/
265 	@embedNullable Nullable!ReadConcern readConcern;
266 }
267 
268 ///
269 enum CursorType
270 {
271 	/**
272 		The default value. A vast majority of cursors will be of this type.
273 	*/
274 	nonTailable,
275 	/**
276 		Tailable means the cursor is not closed when the last data is retrieved.
277 		Rather, the cursor marks the final object’s position. You can resume
278 		using the cursor later, from where it was located, if more data were
279 		received. Like any “latent cursor”, the cursor may become invalid at
280 		some point (CursorNotFound) – for example if the final object it
281 		references were deleted.
282 	*/
283 	tailable,
284 	/**
285 		Combines the tailable option with awaitData, as defined below.
286 
287 		Use with TailableCursor. If we are at the end of the data, block for a
288 		while rather than returning no data. After a timeout period, we do
289 		return as normal. The default is true.
290 	*/
291 	tailableAwait,
292 }
293 
294 /**
295 	See_Also: $(LINK https://www.mongodb.com/docs/manual/reference/command/distinct/)
296 
297 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#id16)
298 */
299 struct DistinctOptions
300 {
301 	/**
302 		Collation allows users to specify language-specific rules for string
303 		comparison, such as rules for letter-case and accent marks.
304 	*/
305 	@embedNullable @errorBefore(WireVersion.v34)
306 	Nullable!Collation collation;
307 
308 	/**
309 		The maximum amount of time to allow the query to run.
310 	*/
311 	@embedNullable
312 	Nullable!long maxTimeMS;
313 
314 	/// ditto
315 	void maxTime(Duration d)
316 	@safe {
317 		maxTimeMS = cast(long)d.total!"msecs";
318 	}
319 
320 	/**
321 		Specifies the read concern. Only compatible with a write stage. (e.g.
322 		`$out`, `$merge`)
323 
324 		Aggregate commands do not support the $(D ReadConcern.Level.linearizable)
325 		level.
326 
327 		Standards: $(LINK https://github.com/mongodb/specifications/blob/7745234f93039a83ae42589a6c0cdbefcffa32fa/source/read-write-concern/read-write-concern.rst)
328 	*/
329 	@embedNullable Nullable!ReadConcern readConcern;
330 
331 	/**
332 		Users can specify an arbitrary string to help trace the operation
333 		through the database profiler, currentOp, and logs.
334 	*/
335 	@embedNullable
336 	Nullable!string comment;
337 }
338 
339 /**
340 	See_Also: $(LINK https://www.mongodb.com/docs/manual/reference/command/count/)
341 		  and $(LINK https://www.mongodb.com/docs/manual/reference/method/db.collection.countDocuments/)
342 
343 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#id16)
344 */
345 struct CountOptions
346 {
347 	/**
348 		Collation allows users to specify language-specific rules for string
349 		comparison, such as rules for letter-case and accent marks.
350 	*/
351 	@embedNullable @errorBefore(WireVersion.v34)
352 	Nullable!Collation collation;
353 
354 	/**
355 		The index to use. Specify either the index name as a string or the index
356 		key pattern.
357 
358 		If specified, then the query system will only consider plans using the
359 		hinted index.
360 	*/
361 	@embedNullable
362 	Nullable!Bson hint;
363 
364 	/**
365 		The maximum number of documents to return.
366 
367 		A negative limit only returns a single batch of results.
368 	*/
369 	@embedNullable
370 	Nullable!long limit;
371 
372 	/**
373 		The maximum amount of time to allow the query to run.
374 	*/
375 	@embedNullable
376 	Nullable!long maxTimeMS;
377 
378 	/// ditto
379 	void maxTime(Duration d)
380 	@safe {
381 		maxTimeMS = cast(long)d.total!"msecs";
382 	}
383 
384 	/**
385 		The number of documents to skip before returning.
386 	*/
387 	@embedNullable
388 	Nullable!long skip;
389 
390 	/**
391 		Specifies the read concern. Only compatible with a write stage. (e.g.
392 		`$out`, `$merge`)
393 
394 		Aggregate commands do not support the $(D ReadConcern.Level.linearizable)
395 		level.
396 
397 		Standards: $(LINK https://github.com/mongodb/specifications/blob/7745234f93039a83ae42589a6c0cdbefcffa32fa/source/read-write-concern/read-write-concern.rst)
398 	*/
399 	@embedNullable Nullable!ReadConcern readConcern;
400 }
401 
402 /**
403 	See_Also: $(LINK https://www.mongodb.com/docs/manual/reference/method/db.collection.estimatedDocumentCount/)
404 
405 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#id16)
406 */
407 struct EstimatedDocumentCountOptions
408 {
409 	/**
410 		The maximum amount of time to allow the query to run.
411 	*/
412 	@embedNullable
413 	Nullable!long maxTimeMS;
414 
415 	/// ditto
416 	void maxTime(Duration d)
417 	@safe {
418 		maxTimeMS = cast(long)d.total!"msecs";
419 	}
420 }
421 
422 /**
423 	Represents available options for an aggregate call
424 
425 	See_Also: $(LINK https://www.mongodb.com/docs/manual/reference/command/aggregate/#dbcmd.aggregate)
426 
427 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#id16)
428 */
429 struct AggregateOptions
430 {
431 	// undocumented because this field isn't a spec field because it is
432 	// out-of-scope for a driver
433 	@embedNullable Nullable!bool explain;
434 
435 	/**
436 		Enables writing to temporary files. When set to true, aggregation
437 		operations can write data to the _tmp subdirectory in the dbPath
438 		directory.
439 	*/
440 	@embedNullable
441 	Nullable!bool allowDiskUse;
442 
443 	// non-optional since 3.6
444 	// get/set by `batchSize`, undocumented in favor of that field
445 	CursorInitArguments cursor;
446 
447 	/// Specifies the initial batch size for the cursor.
448 	ref inout(Nullable!int) batchSize()
449 	return @property inout @safe pure nothrow @nogc @ignore {
450 		return cursor.batchSize;
451 	}
452 
453 	/**
454 		If true, allows the write to opt-out of document level validation.
455 		This only applies when the $out or $merge stage is specified.
456 	*/
457 	@embedNullable @since(WireVersion.v32)
458 	Nullable!bool bypassDocumentValidation;
459 
460 	/**
461 		Collation allows users to specify language-specific rules for string
462 		comparison, such as rules for letter-case and accent marks.
463 	*/
464 	@embedNullable @errorBefore(WireVersion.v34)
465 	Nullable!Collation collation;
466 
467 	/**
468 		Users can specify an arbitrary string to help trace the operation
469 		through the database profiler, currentOp, and logs.
470 	*/
471 	@embedNullable
472 	Nullable!string comment;
473 
474 	/**
475 		The maximum amount of time for the server to wait on new documents to
476 		satisfy a tailable cursor query. This only applies to a TAILABLE_AWAIT
477 		cursor. When the cursor is not a TAILABLE_AWAIT cursor, this option is
478 		ignored.
479 
480 		Note: This option is specified as "maxTimeMS" in the getMore command and
481 		not provided as part of the initial find command.
482 	*/
483 	@embedNullable @since(WireVersion.v32)
484 	Nullable!long maxAwaitTimeMS;
485 
486 	/// ditto
487 	void maxAwaitTime(Duration d)
488 	@safe {
489 		maxAwaitTimeMS = cast(long)d.total!"msecs";
490 	}
491 
492 	/**
493 		Specifies a time limit in milliseconds for processing operations on a
494 		cursor. If you do not specify a value for maxTimeMS, operations will not
495 		time out.
496 	*/
497 	@embedNullable
498 	Nullable!long maxTimeMS;
499 
500 	/// ditto
501 	void maxTime(Duration d)
502 	@safe {
503 		maxTimeMS = cast(long)d.total!"msecs";
504 	}
505 
506 	/**
507 		The index to use for the aggregation. The index is on the initial
508 		collection / view against which the aggregation is run.
509 
510 		The hint does not apply to $lookup and $graphLookup stages.
511 
512 		Specify the index either by the index name as a string or the index key
513 		pattern. If specified, then the query system will only consider plans
514 		using the hinted index.
515 	*/
516 	@embedNullable
517 	Nullable!Bson hint;
518 
519 	/**
520 		Map of parameter names and values. Values must be constant or closed
521 		expressions that do not reference document fields. Parameters can then
522 		be accessed as variables in an aggregate expression context
523 		(e.g. `"$$var"`).
524 
525 		This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
526 	*/
527 	@embedNullable
528 	Nullable!Bson let;
529 
530 	/**
531 		Specifies the read concern. Only compatible with a write stage. (e.g.
532 		`$out`, `$merge`)
533 
534 		Aggregate commands do not support the $(D ReadConcern.Level.linearizable)
535 		level.
536 
537 		Standards: $(LINK https://github.com/mongodb/specifications/blob/7745234f93039a83ae42589a6c0cdbefcffa32fa/source/read-write-concern/read-write-concern.rst)
538 	*/
539 	@embedNullable Nullable!ReadConcern readConcern;
540 }
541 
542 /**
543 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#insert-update-replace-delete-and-bulk-writes)
544 */
545 struct BulkWriteOptions {
546 
547 	/**
548 		If true, when a write fails, return without performing the remaining
549 		writes. If false, when a write fails, continue with the remaining writes,
550 		if any.
551 
552 		Defaults to true.
553 	*/
554 	@embedNullable
555 	Nullable!bool ordered;
556 
557 	/**
558 		If true, allows the write to opt-out of document level validation.
559 
560 		For servers < 3.2, this option is ignored and not sent as document
561 		validation is not available.
562 
563 		For unacknowledged writes using OP_INSERT, OP_UPDATE, or OP_DELETE, the
564 		driver MUST raise an error if the caller explicitly provides a value.
565 	*/
566 	@embedNullable
567 	Nullable!bool bypassDocumentValidation;
568 
569 	/**
570 		A document that expresses the
571 		$(LINK2 https://www.mongodb.com/docs/manual/reference/write-concern/,write concern)
572 		of the insert command. Omit to use the default write concern.
573 	*/
574 	@embedNullable
575 	Nullable!WriteConcern writeConcern;
576 
577 	/**
578 		Users can specify an arbitrary string to help trace the operation
579 		through the database profiler, currentOp, and logs.
580 	*/
581 	@embedNullable
582 	Nullable!string comment;
583 }
584 
585 /**
586 	See_Also: $(LINK https://docs.mongodb.com/manual/reference/command/insert/)
587 
588 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#insert-update-replace-delete-and-bulk-writes)
589 */
590 struct InsertOneOptions {
591 	/**
592 		If true, allows the write to opt-out of document level validation.
593 
594 		For servers < 3.2, this option is ignored and not sent as document
595 		validation is not available.
596 	*/
597 	@embedNullable
598 	Nullable!bool bypassDocumentValidation;
599 
600 	/**
601 		A document that expresses the
602 		$(LINK2 https://www.mongodb.com/docs/manual/reference/write-concern/,write concern)
603 		of the insert command. Omit to use the default write concern.
604 	*/
605 	@embedNullable
606 	Nullable!WriteConcern writeConcern;
607 
608 	/**
609 		Users can specify an arbitrary string to help trace the operation
610 		through the database profiler, currentOp, and logs.
611 	*/
612 	@embedNullable
613 	Nullable!string comment;
614 }
615 
616 /**
617 	See_Also: $(LINK https://docs.mongodb.com/manual/reference/command/insert/)
618 
619 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#insert-update-replace-delete-and-bulk-writes)
620 */
621 struct InsertManyOptions {
622 	/**
623 		If true, allows the write to opt-out of document level validation.
624 
625 		For servers < 3.2, this option is ignored and not sent as document
626 		validation is not available.
627 	*/
628 	@embedNullable
629 	Nullable!bool bypassDocumentValidation;
630 
631 	/**
632 		If true, when an insert fails, return without performing the remaining
633 		writes. If false, when a write fails, continue with the remaining writes,
634 		if any.
635 
636 		Defaults to true.
637 	*/
638 	@embedNullable
639 	Nullable!bool ordered;
640 
641 	/**
642 		A document that expresses the
643 		$(LINK2 https://www.mongodb.com/docs/manual/reference/write-concern/,write concern)
644 		of the insert command. Omit to use the default write concern.
645 	*/
646 	@embedNullable
647 	Nullable!WriteConcern writeConcern;
648 
649 	/**
650 		Users can specify an arbitrary string to help trace the operation
651 		through the database profiler, currentOp, and logs.
652 	*/
653 	@embedNullable
654 	Nullable!string comment;
655 }
656 
657 /**
658 	See_Also: $(LINK https://docs.mongodb.com/manual/reference/command/update/)
659 
660 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#insert-update-replace-delete-and-bulk-writes)
661 */
662 struct UpdateOptions {
663 	/**
664 		A set of filters specifying to which array elements an update should
665 		apply.
666 	*/
667 	@embedNullable @errorBefore(WireVersion.v36)
668 	Nullable!(Bson[]) arrayFilters;
669 
670 	/**
671 		If true, allows the write to opt-out of document level validation.
672 
673 		For servers < 3.2, this option is ignored and not sent as document
674 		validation is not available.
675 	*/
676 	@embedNullable @since(WireVersion.v32)
677 	Nullable!bool bypassDocumentValidation;
678 
679 	/**
680 		Collation allows users to specify language-specific rules for string
681 		comparison, such as rules for letter-case and accent marks.
682 	*/
683 	@embedNullable @errorBefore(WireVersion.v34)
684 	Nullable!Collation collation;
685 
686 	/**
687 		The index to use. Specify either the index name as a string or the index
688 		key pattern.
689 
690 		If specified, then the query system will only consider plans using the
691 		hinted index.
692 	*/
693 	@embedNullable
694 	Nullable!Bson hint;
695 
696 	/**
697 		When true, creates a new document if no document matches the query.
698 	*/
699 	@embedNullable
700 	Nullable!bool upsert;
701 
702 	/**
703 		A document that expresses the
704 		$(LINK2 https://www.mongodb.com/docs/manual/reference/write-concern/,write concern)
705 		of the insert command. Omit to use the default write concern.
706 	*/
707 	@embedNullable
708 	Nullable!WriteConcern writeConcern;
709 
710 	/**
711 		Users can specify an arbitrary string to help trace the operation
712 		through the database profiler, currentOp, and logs.
713 	*/
714 	@embedNullable
715 	Nullable!string comment;
716 }
717 
718 /**
719 	See_Also: $(LINK https://docs.mongodb.com/manual/reference/command/update/)
720 
721 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#insert-update-replace-delete-and-bulk-writes)
722 */
723 struct ReplaceOptions {
724 	/**
725 		If true, allows the write to opt-out of document level validation.
726 
727 		For servers < 3.2, this option is ignored and not sent as document
728 		validation is not available.
729 	*/
730 	@embedNullable
731 	Nullable!bool bypassDocumentValidation;
732 
733 	/**
734 		Collation allows users to specify language-specific rules for string
735 		comparison, such as rules for letter-case and accent marks.
736 	*/
737 	@embedNullable @errorBefore(WireVersion.v34)
738 	Nullable!Collation collation;
739 
740 	/**
741 		The index to use. Specify either the index name as a string or the index
742 		key pattern.
743 
744 		If specified, then the query system will only consider plans using the
745 		hinted index.
746 	*/
747 	@embedNullable
748 	Nullable!Bson hint;
749 
750 	/**
751 		When true, creates a new document if no document matches the query.
752 	*/
753 	@embedNullable
754 	Nullable!bool upsert;
755 
756 	/**
757 		A document that expresses the
758 		$(LINK2 https://www.mongodb.com/docs/manual/reference/write-concern/,write concern)
759 		of the insert command. Omit to use the default write concern.
760 	*/
761 	@embedNullable
762 	Nullable!WriteConcern writeConcern;
763 
764 	/**
765 		Users can specify an arbitrary string to help trace the operation
766 		through the database profiler, currentOp, and logs.
767 	*/
768 	@embedNullable
769 	Nullable!string comment;
770 }
771 
772 /**
773 	See_Also: $(LINK https://docs.mongodb.com/manual/reference/command/delete/)
774 
775 	Standards: $(LINK https://github.com/mongodb/specifications/blob/525dae0aa8791e782ad9dd93e507b60c55a737bb/source/crud/crud.rst#insert-update-replace-delete-and-bulk-writes)
776 */
777 struct DeleteOptions {
778 	/**
779 		Collation allows users to specify language-specific rules for string
780 		comparison, such as rules for letter-case and accent marks.
781 	*/
782 	@embedNullable @errorBefore(WireVersion.v34)
783 	Nullable!Collation collation;
784 
785 	/**
786 		The index to use. Specify either the index name as a string or the index
787 		key pattern.
788 
789 		If specified, then the query system will only consider plans using the
790 		hinted index.
791 	*/
792 	@embedNullable
793 	Nullable!Bson hint;
794 
795 	/**
796 		A document that expresses the
797 		$(LINK2 https://www.mongodb.com/docs/manual/reference/write-concern/,write concern)
798 		of the insert command. Omit to use the default write concern.
799 	*/
800 	@embedNullable
801 	Nullable!WriteConcern writeConcern;
802 
803 	/**
804 		Users can specify an arbitrary string to help trace the operation
805 		through the database profiler, currentOp, and logs.
806 	*/
807 	@embedNullable
808 	Nullable!string comment;
809 
810 	/**
811 		Map of parameter names and values. Values must be constant or closed
812 		expressions that do not reference document fields. Parameters can then
813 		be accessed as variables in an aggregate expression context
814 		(e.g. `"$$var"`).
815 
816 		This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
817 	*/
818 	@embedNullable
819 	Nullable!Bson let;
820 }
821 
822 struct InsertOneResult {
823 	/**
824 		The identifier that was automatically generated, if not set.
825 	*/
826 	BsonObjectID insertedId;
827 }
828 
829 struct InsertManyResult {
830 	/**
831 		The identifiers that were automatically generated, if not set.
832 	*/
833 	BsonObjectID[size_t] insertedIds;
834 	/**
835 		The number of documents that were inserted.
836 	*/
837 	long insertedCount;
838 }
839 
840 struct DeleteResult {
841 	/**
842 		The number of documents that were deleted.
843 	*/
844 	long deletedCount;
845 }
846 
847 struct UpdateResult {
848 	/**
849 		The number of documents that matched the filter.
850 	*/
851 	long matchedCount;
852 
853 	/**
854 		The number of documents that were modified.
855 	*/
856 	long modifiedCount;
857 
858 	/**
859 		The identifier of the inserted document if an upsert took place. Can be
860 		none if no upserts took place, can be multiple if using the updateImpl
861 		helper.
862 	*/
863 	BsonObjectID[] upsertedIds;
864 }
865 
866 /**
867 	Describes a failed write command result for a single document.
868 
869 	See_Also: $(LINK https://www.mongodb.com/docs/manual/reference/method/WriteResult/)
870 
871 	Standards: $(LINK https://github.com/mongodb/specifications/blob/0b6b96b758259edc91c2fc475bcf08eea54e08e2/source/crud/crud.rst#L1745)
872 */
873 struct BulkWriteError
874 {
875 	/**
876 	 * An integer value identifying the write error.
877 	 */
878 	int code;
879 	/**
880 	 * A document providing more information about the write error (e.g. details
881 	 * pertaining to document validation).
882 	 */
883 	@optional @name("errInfo") Bson details;
884 	/**
885 	 * A description of the error.
886 	 */
887 	@optional @name("errmsg") string message;
888 	/**
889 	 * The index of the request that errored.
890 	 */
891 	@optional int index;
892 }
893 
894 /**
895  * Exception for partially or fully failed writes from `insert`, `update` or
896  * `delete`.
897  */
898 class MongoBulkWriteException : MongoException
899 {
900 @safe:
901 	BulkWriteError[] errors;
902 
903 	this(BulkWriteError[] errors, string file = __FILE__,
904 			size_t line = __LINE__, Throwable next = null)
905 	{
906 		import std.algorithm : map;
907 		import std.string : join;
908 
909 		super("Failed to write all documents:\n"
910 			~ errors.map!(e => "- " ~ e.message).join("\n"), file, line, next);
911 
912 		this.errors = errors;
913 	}
914 }
915 
916 /**
917  * Handles the raw DB response from `insert`, `update` or `delete` operations.
918  *
919  * If the `countField` template argument is set, that field is set on `result`
920  * to `dbResult["n"]`, if it exists.
921  */
922 package(vibe.db.mongo) void handleWriteResult(string countField = null, T)(
923 	Bson dbResult, ref T result, string file = __FILE__, size_t line = __LINE__)
924 {
925 	auto dbObject = dbResult.get!(Bson[string]);
926 	static if (countField != null)
927 	{
928 		if (auto n = "n" in dbObject)
929 			__traits(getMember, result, countField) = n.to!long;
930 	}
931 
932 	if (auto writeErrors = "writeErrors" in dbObject)
933 	{
934 		if (writeErrors.type == Bson.Type.array)
935 		{
936 			auto errors = deserializeBson!(BulkWriteError[])(*writeErrors);
937 			if (errors.length > 0)
938 				throw new MongoBulkWriteException(errors, file, line);
939 		}
940 	}
941 }