1// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7// NOTE: Any time this file is modified, a WEBSITE ticket should be opened to sync the changes with
8// the "What is MongoDB" webpage, which the example was originally added to as part of WEBSITE-5148.
9
10package documentation_examples
11
12import (
13	"context"
14	"fmt"
15	"io/ioutil"
16	logger "log"
17	"sync/atomic"
18	"testing"
19	"time"
20
21	"github.com/stretchr/testify/require"
22	"go.mongodb.org/mongo-driver/bson"
23	"go.mongodb.org/mongo-driver/bson/primitive"
24	"go.mongodb.org/mongo-driver/mongo"
25	"go.mongodb.org/mongo-driver/mongo/options"
26	"go.mongodb.org/mongo-driver/mongo/readconcern"
27	"go.mongodb.org/mongo-driver/mongo/readpref"
28	"go.mongodb.org/mongo-driver/mongo/writeconcern"
29)
30
31func requireCursorLength(t *testing.T, cursor *mongo.Cursor, length int) {
32	i := 0
33	for cursor.Next(context.Background()) {
34		i++
35	}
36
37	require.NoError(t, cursor.Err())
38	require.Equal(t, i, length)
39}
40
41func containsKey(doc bson.Raw, key ...string) bool {
42	_, err := doc.LookupErr(key...)
43	if err != nil {
44		return false
45	}
46	return true
47}
48
49func parseDate(t *testing.T, dateString string) time.Time {
50	rfc3339MilliLayout := "2006-01-02T15:04:05.999Z07:00" // layout defined with Go reference time
51	parsedDate, err := time.Parse(rfc3339MilliLayout, dateString)
52
53	require.NoError(t, err)
54	return parsedDate
55}
56
57// InsertExamples contains examples for insert operations.
58func InsertExamples(t *testing.T, db *mongo.Database) {
59	coll := db.Collection("inventory_insert")
60
61	err := coll.Drop(context.Background())
62	require.NoError(t, err)
63
64	{
65		// Start Example 1
66
67		result, err := coll.InsertOne(
68			context.Background(),
69			bson.D{
70				{"item", "canvas"},
71				{"qty", 100},
72				{"tags", bson.A{"cotton"}},
73				{"size", bson.D{
74					{"h", 28},
75					{"w", 35.5},
76					{"uom", "cm"},
77				}},
78			})
79
80		// End Example 1
81
82		require.NoError(t, err)
83		require.NotNil(t, result.InsertedID)
84	}
85
86	{
87		// Start Example 2
88
89		cursor, err := coll.Find(
90			context.Background(),
91			bson.D{{"item", "canvas"}},
92		)
93
94		// End Example 2
95
96		require.NoError(t, err)
97		requireCursorLength(t, cursor, 1)
98
99	}
100
101	{
102		// Start Example 3
103
104		result, err := coll.InsertMany(
105			context.Background(),
106			[]interface{}{
107				bson.D{
108					{"item", "journal"},
109					{"qty", int32(25)},
110					{"tags", bson.A{"blank", "red"}},
111					{"size", bson.D{
112						{"h", 14},
113						{"w", 21},
114						{"uom", "cm"},
115					}},
116				},
117				bson.D{
118					{"item", "mat"},
119					{"qty", int32(25)},
120					{"tags", bson.A{"gray"}},
121					{"size", bson.D{
122						{"h", 27.9},
123						{"w", 35.5},
124						{"uom", "cm"},
125					}},
126				},
127				bson.D{
128					{"item", "mousepad"},
129					{"qty", 25},
130					{"tags", bson.A{"gel", "blue"}},
131					{"size", bson.D{
132						{"h", 19},
133						{"w", 22.85},
134						{"uom", "cm"},
135					}},
136				},
137			})
138
139		// End Example 3
140
141		require.NoError(t, err)
142		require.Len(t, result.InsertedIDs, 3)
143	}
144}
145
146// QueryToplevelFieldsExamples contains examples for querying top-level fields.
147func QueryToplevelFieldsExamples(t *testing.T, db *mongo.Database) {
148	coll := db.Collection("inventory_query_top")
149
150	err := coll.Drop(context.Background())
151	require.NoError(t, err)
152
153	{
154		// Start Example 6
155
156		docs := []interface{}{
157			bson.D{
158				{"item", "journal"},
159				{"qty", 25},
160				{"size", bson.D{
161					{"h", 14},
162					{"w", 21},
163					{"uom", "cm"},
164				}},
165				{"status", "A"},
166			},
167			bson.D{
168				{"item", "notebook"},
169				{"qty", 50},
170				{"size", bson.D{
171					{"h", 8.5},
172					{"w", 11},
173					{"uom", "in"},
174				}},
175				{"status", "A"},
176			},
177			bson.D{
178				{"item", "paper"},
179				{"qty", 100},
180				{"size", bson.D{
181					{"h", 8.5},
182					{"w", 11},
183					{"uom", "in"},
184				}},
185				{"status", "D"},
186			},
187			bson.D{
188				{"item", "planner"},
189				{"qty", 75},
190				{"size", bson.D{
191					{"h", 22.85},
192					{"w", 30},
193					{"uom", "cm"},
194				}},
195				{"status", "D"},
196			},
197			bson.D{
198				{"item", "postcard"},
199				{"qty", 45},
200				{"size", bson.D{
201					{"h", 10},
202					{"w", 15.25},
203					{"uom", "cm"},
204				}},
205				{"status", "A"},
206			},
207		}
208
209		result, err := coll.InsertMany(context.Background(), docs)
210
211		// End Example 6
212
213		require.NoError(t, err)
214		require.Len(t, result.InsertedIDs, 5)
215	}
216
217	{
218		// Start Example 7
219
220		cursor, err := coll.Find(
221			context.Background(),
222			bson.D{},
223		)
224
225		// End Example 7
226
227		require.NoError(t, err)
228		requireCursorLength(t, cursor, 5)
229	}
230
231	{
232		// Start Example 9
233
234		cursor, err := coll.Find(
235			context.Background(),
236			bson.D{{"status", "D"}},
237		)
238
239		// End Example 9
240
241		require.NoError(t, err)
242		requireCursorLength(t, cursor, 2)
243	}
244
245	{
246		// Start Example 10
247
248		cursor, err := coll.Find(
249			context.Background(),
250			bson.D{{"status", bson.D{{"$in", bson.A{"A", "D"}}}}})
251
252		// End Example 10
253
254		require.NoError(t, err)
255		requireCursorLength(t, cursor, 5)
256	}
257
258	{
259		// Start Example 11
260
261		cursor, err := coll.Find(
262			context.Background(),
263			bson.D{
264				{"status", "A"},
265				{"qty", bson.D{{"$lt", 30}}},
266			})
267
268		// End Example 11
269
270		require.NoError(t, err)
271		requireCursorLength(t, cursor, 1)
272	}
273
274	{
275		// Start Example 12
276
277		cursor, err := coll.Find(
278			context.Background(),
279			bson.D{
280				{"$or",
281					bson.A{
282						bson.D{{"status", "A"}},
283						bson.D{{"qty", bson.D{{"$lt", 30}}}},
284					}},
285			})
286
287		// End Example 12
288
289		require.NoError(t, err)
290		requireCursorLength(t, cursor, 3)
291	}
292
293	{
294		// Start Example 13
295
296		cursor, err := coll.Find(
297			context.Background(),
298			bson.D{
299				{"status", "A"},
300				{"$or", bson.A{
301					bson.D{{"qty", bson.D{{"$lt", 30}}}},
302					bson.D{{"item", primitive.Regex{Pattern: "^p", Options: ""}}},
303				}},
304			})
305
306		// End Example 13
307
308		require.NoError(t, err)
309		requireCursorLength(t, cursor, 2)
310	}
311
312}
313
314// QueryEmbeddedDocumentsExamples contains examples for querying embedded document fields.
315func QueryEmbeddedDocumentsExamples(t *testing.T, db *mongo.Database) {
316	coll := db.Collection("inventory_query_embedded")
317
318	err := coll.Drop(context.Background())
319	require.NoError(t, err)
320
321	{
322		// Start Example 14
323
324		docs := []interface{}{
325			bson.D{
326				{"item", "journal"},
327				{"qty", 25},
328				{"size", bson.D{
329					{"h", 14},
330					{"w", 21},
331					{"uom", "cm"},
332				}},
333				{"status", "A"},
334			},
335			bson.D{
336				{"item", "notebook"},
337				{"qty", 50},
338				{"size", bson.D{
339					{"h", 8.5},
340					{"w", 11},
341					{"uom", "in"},
342				}},
343				{"status", "A"},
344			},
345			bson.D{
346				{"item", "paper"},
347				{"qty", 100},
348				{"size", bson.D{
349					{"h", 8.5},
350					{"w", 11},
351					{"uom", "in"},
352				}},
353				{"status", "D"},
354			},
355			bson.D{
356				{"item", "planner"},
357				{"qty", 75},
358				{"size", bson.D{
359					{"h", 22.85},
360					{"w", 30},
361					{"uom", "cm"},
362				}},
363				{"status", "D"},
364			},
365			bson.D{
366				{"item", "postcard"},
367				{"qty", 45},
368				{"size", bson.D{
369					{"h", 10},
370					{"w", 15.25},
371					{"uom", "cm"},
372				}},
373				{"status", "A"},
374			},
375		}
376
377		result, err := coll.InsertMany(context.Background(), docs)
378
379		// End Example 14
380
381		require.NoError(t, err)
382		require.Len(t, result.InsertedIDs, 5)
383	}
384
385	{
386		// Start Example 15
387
388		cursor, err := coll.Find(
389			context.Background(),
390			bson.D{
391				{"size", bson.D{
392					{"h", 14},
393					{"w", 21},
394					{"uom", "cm"},
395				}},
396			})
397
398		// End Example 15
399
400		require.NoError(t, err)
401		requireCursorLength(t, cursor, 1)
402	}
403
404	{
405		// Start Example 16
406
407		cursor, err := coll.Find(
408			context.Background(),
409			bson.D{
410				{"size", bson.D{
411					{"w", 21},
412					{"h", 14},
413					{"uom", "cm"},
414				}},
415			})
416
417		// End Example 16
418
419		require.NoError(t, err)
420		requireCursorLength(t, cursor, 0)
421	}
422
423	{
424		// Start Example 17
425
426		cursor, err := coll.Find(
427			context.Background(),
428			bson.D{{"size.uom", "in"}},
429		)
430
431		// End Example 17
432
433		require.NoError(t, err)
434		requireCursorLength(t, cursor, 2)
435	}
436
437	{
438		// Start Example 18
439
440		cursor, err := coll.Find(
441			context.Background(),
442			bson.D{
443				{"size.h", bson.D{
444					{"$lt", 15},
445				}},
446			})
447
448		// End Example 18
449
450		require.NoError(t, err)
451		requireCursorLength(t, cursor, 4)
452	}
453
454	{
455		// Start Example 19
456
457		cursor, err := coll.Find(
458			context.Background(),
459			bson.D{
460				{"size.h", bson.D{
461					{"$lt", 15},
462				}},
463				{"size.uom", "in"},
464				{"status", "D"},
465			})
466
467		// End Example 19
468
469		require.NoError(t, err)
470		requireCursorLength(t, cursor, 1)
471	}
472
473}
474
475// QueryArraysExamples contains examples for querying array fields.
476func QueryArraysExamples(t *testing.T, db *mongo.Database) {
477	coll := db.Collection("inventory_query_array")
478
479	err := coll.Drop(context.Background())
480	require.NoError(t, err)
481
482	{
483		// Start Example 20
484
485		docs := []interface{}{
486			bson.D{
487				{"item", "journal"},
488				{"qty", 25},
489				{"tags", bson.A{"blank", "red"}},
490				{"dim_cm", bson.A{14, 21}},
491			},
492			bson.D{
493				{"item", "notebook"},
494				{"qty", 50},
495				{"tags", bson.A{"red", "blank"}},
496				{"dim_cm", bson.A{14, 21}},
497			},
498			bson.D{
499				{"item", "paper"},
500				{"qty", 100},
501				{"tags", bson.A{"red", "blank", "plain"}},
502				{"dim_cm", bson.A{14, 21}},
503			},
504			bson.D{
505				{"item", "planner"},
506				{"qty", 75},
507				{"tags", bson.A{"blank", "red"}},
508				{"dim_cm", bson.A{22.85, 30}},
509			},
510			bson.D{
511				{"item", "postcard"},
512				{"qty", 45},
513				{"tags", bson.A{"blue"}},
514				{"dim_cm", bson.A{10, 15.25}},
515			},
516		}
517
518		result, err := coll.InsertMany(context.Background(), docs)
519
520		// End Example 20
521
522		require.NoError(t, err)
523		require.Len(t, result.InsertedIDs, 5)
524	}
525
526	{
527		// Start Example 21
528
529		cursor, err := coll.Find(
530			context.Background(),
531			bson.D{{"tags", bson.A{"red", "blank"}}},
532		)
533
534		// End Example 21
535
536		require.NoError(t, err)
537		requireCursorLength(t, cursor, 1)
538	}
539
540	{
541		// Start Example 22
542
543		cursor, err := coll.Find(
544			context.Background(),
545			bson.D{
546				{"tags", bson.D{{"$all", bson.A{"red", "blank"}}}},
547			})
548
549		// End Example 22
550
551		require.NoError(t, err)
552		requireCursorLength(t, cursor, 4)
553	}
554
555	{
556		// Start Example 23
557
558		cursor, err := coll.Find(
559			context.Background(),
560			bson.D{
561				{"tags", "red"},
562			})
563
564		// End Example 23
565
566		require.NoError(t, err)
567		requireCursorLength(t, cursor, 4)
568	}
569
570	{
571		// Start Example 24
572
573		cursor, err := coll.Find(
574			context.Background(),
575			bson.D{
576				{"dim_cm", bson.D{
577					{"$gt", 25},
578				}},
579			})
580
581		// End Example 24
582
583		require.NoError(t, err)
584		requireCursorLength(t, cursor, 1)
585	}
586
587	{
588		// Start Example 25
589
590		cursor, err := coll.Find(
591			context.Background(),
592			bson.D{
593				{"dim_cm", bson.D{
594					{"$gt", 15},
595					{"$lt", 20},
596				}},
597			})
598
599		// End Example 25
600
601		require.NoError(t, err)
602		requireCursorLength(t, cursor, 4)
603	}
604
605	{
606		// Start Example 26
607
608		cursor, err := coll.Find(
609			context.Background(),
610			bson.D{
611				{"dim_cm", bson.D{
612					{"$elemMatch", bson.D{
613						{"$gt", 22},
614						{"$lt", 30},
615					}},
616				}},
617			})
618
619		// End Example 26
620
621		require.NoError(t, err)
622		requireCursorLength(t, cursor, 1)
623	}
624
625	{
626		// Start Example 27
627
628		cursor, err := coll.Find(
629			context.Background(),
630			bson.D{
631				{"dim_cm.1", bson.D{
632					{"$gt", 25},
633				}},
634			})
635
636		// End Example 27
637
638		require.NoError(t, err)
639		requireCursorLength(t, cursor, 1)
640	}
641
642	{
643		// Start Example 28
644
645		cursor, err := coll.Find(
646			context.Background(),
647			bson.D{
648				{"tags", bson.D{
649					{"$size", 3},
650				}},
651			})
652
653		// End Example 28
654
655		require.NoError(t, err)
656		requireCursorLength(t, cursor, 1)
657	}
658
659}
660
661// QueryArrayEmbeddedDocumentsExamples contains examples for querying fields with arrays and embedded documents.
662func QueryArrayEmbeddedDocumentsExamples(t *testing.T, db *mongo.Database) {
663	coll := db.Collection("inventory_query_array_embedded")
664
665	err := coll.Drop(context.Background())
666	require.NoError(t, err)
667
668	{
669		// Start Example 29
670
671		docs := []interface{}{
672			bson.D{
673				{"item", "journal"},
674				{"instock", bson.A{
675					bson.D{
676						{"warehouse", "A"},
677						{"qty", 5},
678					},
679					bson.D{
680						{"warehouse", "C"},
681						{"qty", 15},
682					},
683				}},
684			},
685			bson.D{
686				{"item", "notebook"},
687				{"instock", bson.A{
688					bson.D{
689						{"warehouse", "C"},
690						{"qty", 5},
691					},
692				}},
693			},
694			bson.D{
695				{"item", "paper"},
696				{"instock", bson.A{
697					bson.D{
698						{"warehouse", "A"},
699						{"qty", 60},
700					},
701					bson.D{
702						{"warehouse", "B"},
703						{"qty", 15},
704					},
705				}},
706			},
707			bson.D{
708				{"item", "planner"},
709				{"instock", bson.A{
710					bson.D{
711						{"warehouse", "A"},
712						{"qty", 40},
713					},
714					bson.D{
715						{"warehouse", "B"},
716						{"qty", 5},
717					},
718				}},
719			},
720			bson.D{
721				{"item", "postcard"},
722				{"instock", bson.A{
723					bson.D{
724						{"warehouse", "B"},
725						{"qty", 15},
726					},
727					bson.D{
728						{"warehouse", "C"},
729						{"qty", 35},
730					},
731				}},
732			},
733		}
734
735		result, err := coll.InsertMany(context.Background(), docs)
736
737		// End Example 29
738
739		require.NoError(t, err)
740		require.Len(t, result.InsertedIDs, 5)
741	}
742
743	{
744		// Start Example 30
745
746		cursor, err := coll.Find(
747			context.Background(),
748			bson.D{
749				{"instock", bson.D{
750					{"warehouse", "A"},
751					{"qty", 5},
752				}},
753			})
754
755		// End Example 30
756
757		require.NoError(t, err)
758		requireCursorLength(t, cursor, 1)
759	}
760
761	{
762		// Start Example 31
763
764		cursor, err := coll.Find(
765			context.Background(),
766			bson.D{
767				{"instock", bson.D{
768					{"qty", 5},
769					{"warehouse", "A"},
770				}},
771			})
772
773		// End Example 31
774
775		require.NoError(t, err)
776		requireCursorLength(t, cursor, 0)
777	}
778
779	{
780		// Start Example 32
781
782		cursor, err := coll.Find(
783			context.Background(),
784			bson.D{
785				{"instock.0.qty", bson.D{
786					{"$lte", 20},
787				}},
788			})
789
790		// End Example 32
791
792		require.NoError(t, err)
793		requireCursorLength(t, cursor, 3)
794	}
795
796	{
797		// Start Example 33
798
799		cursor, err := coll.Find(
800			context.Background(),
801			bson.D{
802				{"instock.qty", bson.D{
803					{"$lte", 20},
804				}},
805			})
806
807		// End Example 33
808
809		require.NoError(t, err)
810		requireCursorLength(t, cursor, 5)
811	}
812
813	{
814		// Start Example 34
815
816		cursor, err := coll.Find(
817			context.Background(),
818			bson.D{
819				{"instock", bson.D{
820					{"$elemMatch", bson.D{
821						{"qty", 5},
822						{"warehouse", "A"},
823					}},
824				}},
825			})
826
827		// End Example 34
828
829		require.NoError(t, err)
830		requireCursorLength(t, cursor, 1)
831	}
832
833	{
834		// Start Example 35
835
836		cursor, err := coll.Find(
837			context.Background(),
838			bson.D{
839				{"instock", bson.D{
840					{"$elemMatch", bson.D{
841						{"qty", bson.D{
842							{"$gt", 10},
843							{"$lte", 20},
844						}},
845					}},
846				}},
847			})
848
849		// End Example 35
850
851		require.NoError(t, err)
852		requireCursorLength(t, cursor, 3)
853	}
854
855	{
856		// Start Example 36
857
858		cursor, err := coll.Find(
859			context.Background(),
860			bson.D{
861				{"instock.qty", bson.D{
862					{"$gt", 10},
863					{"$lte", 20},
864				}},
865			})
866
867		// End Example 36
868
869		require.NoError(t, err)
870		requireCursorLength(t, cursor, 4)
871	}
872
873	{
874		// Start Example 37
875
876		cursor, err := coll.Find(
877			context.Background(),
878			bson.D{
879				{"instock.qty", 5},
880				{"instock.warehouse", "A"},
881			})
882
883		// End Example 37
884
885		require.NoError(t, err)
886		requireCursorLength(t, cursor, 2)
887	}
888}
889
890// QueryNullMissingFieldsExamples contains examples for querying fields that are null or missing.
891func QueryNullMissingFieldsExamples(t *testing.T, db *mongo.Database) {
892	coll := db.Collection("inventory_query_null_missing")
893
894	err := coll.Drop(context.Background())
895	require.NoError(t, err)
896
897	{
898		// Start Example 38
899
900		docs := []interface{}{
901			bson.D{
902				{"_id", 1},
903				{"item", nil},
904			},
905			bson.D{
906				{"_id", 2},
907			},
908		}
909
910		result, err := coll.InsertMany(context.Background(), docs)
911
912		// End Example 38
913
914		require.NoError(t, err)
915		require.Len(t, result.InsertedIDs, 2)
916	}
917
918	{
919		// Start Example 39
920
921		cursor, err := coll.Find(
922			context.Background(),
923			bson.D{
924				{"item", nil},
925			})
926
927		// End Example 39
928
929		require.NoError(t, err)
930		requireCursorLength(t, cursor, 2)
931	}
932
933	{
934		// Start Example 40
935
936		cursor, err := coll.Find(
937			context.Background(),
938			bson.D{
939				{"item", bson.D{
940					{"$type", 10},
941				}},
942			})
943
944		// End Example 40
945
946		require.NoError(t, err)
947		requireCursorLength(t, cursor, 1)
948	}
949
950	{
951		// Start Example 41
952
953		cursor, err := coll.Find(
954			context.Background(),
955			bson.D{
956				{"item", bson.D{
957					{"$exists", false},
958				}},
959			})
960
961		// End Example 41
962
963		require.NoError(t, err)
964		requireCursorLength(t, cursor, 1)
965	}
966}
967
968// ProjectionExamples contains examples for specifying projections in find operations.
969func ProjectionExamples(t *testing.T, db *mongo.Database) {
970	coll := db.Collection("inventory_project")
971
972	err := coll.Drop(context.Background())
973	require.NoError(t, err)
974
975	{
976		// Start Example 42
977
978		docs := []interface{}{
979			bson.D{
980				{"item", "journal"},
981				{"status", "A"},
982				{"size", bson.D{
983					{"h", 14},
984					{"w", 21},
985					{"uom", "cm"},
986				}},
987				{"instock", bson.A{
988					bson.D{
989						{"warehouse", "A"},
990						{"qty", 5},
991					},
992				}},
993			},
994			bson.D{
995				{"item", "notebook"},
996				{"status", "A"},
997				{"size", bson.D{
998					{"h", 8.5},
999					{"w", 11},
1000					{"uom", "in"},
1001				}},
1002				{"instock", bson.A{
1003					bson.D{
1004						{"warehouse", "EC"},
1005						{"qty", 5},
1006					},
1007				}},
1008			},
1009			bson.D{
1010				{"item", "paper"},
1011				{"status", "D"},
1012				{"size", bson.D{
1013					{"h", 8.5},
1014					{"w", 11},
1015					{"uom", "in"},
1016				}},
1017				{"instock", bson.A{
1018					bson.D{
1019						{"warehouse", "A"},
1020						{"qty", 60},
1021					},
1022				}},
1023			},
1024			bson.D{
1025				{"item", "planner"},
1026				{"status", "D"},
1027				{"size", bson.D{
1028					{"h", 22.85},
1029					{"w", 30},
1030					{"uom", "cm"},
1031				}},
1032				{"instock", bson.A{
1033					bson.D{
1034						{"warehouse", "A"},
1035						{"qty", 40},
1036					},
1037				}},
1038			},
1039			bson.D{
1040				{"item", "postcard"},
1041				{"status", "A"},
1042				{"size", bson.D{
1043					{"h", 10},
1044					{"w", 15.25},
1045					{"uom", "cm"},
1046				}},
1047				{"instock", bson.A{
1048					bson.D{
1049						{"warehouse", "B"},
1050						{"qty", 15},
1051					},
1052					bson.D{
1053						{"warehouse", "EC"},
1054						{"qty", 35},
1055					},
1056				}},
1057			},
1058		}
1059
1060		result, err := coll.InsertMany(context.Background(), docs)
1061
1062		// End Example 42
1063
1064		require.NoError(t, err)
1065		require.Len(t, result.InsertedIDs, 5)
1066	}
1067
1068	{
1069		// Start Example 43
1070
1071		cursor, err := coll.Find(
1072			context.Background(),
1073			bson.D{{"status", "A"}},
1074		)
1075
1076		// End Example 43
1077
1078		require.NoError(t, err)
1079		requireCursorLength(t, cursor, 3)
1080	}
1081
1082	{
1083		// Start Example 44
1084
1085		projection := bson.D{
1086			{"item", 1},
1087			{"status", 1},
1088		}
1089
1090		cursor, err := coll.Find(
1091			context.Background(),
1092			bson.D{
1093				{"status", "A"},
1094			},
1095			options.Find().SetProjection(projection),
1096		)
1097
1098		// End Example 44
1099
1100		require.NoError(t, err)
1101
1102		for cursor.Next(context.Background()) {
1103			doc := cursor.Current
1104
1105			require.True(t, containsKey(doc, "_id"))
1106			require.True(t, containsKey(doc, "item"))
1107			require.True(t, containsKey(doc, "status"))
1108			require.False(t, containsKey(doc, "size"))
1109			require.False(t, containsKey(doc, "instock"))
1110		}
1111
1112		require.NoError(t, cursor.Err())
1113	}
1114
1115	{
1116		// Start Example 45
1117
1118		projection := bson.D{
1119			{"item", 1},
1120			{"status", 1},
1121			{"_id", 0},
1122		}
1123
1124		cursor, err := coll.Find(
1125			context.Background(),
1126			bson.D{
1127				{"status", "A"},
1128			},
1129			options.Find().SetProjection(projection),
1130		)
1131
1132		// End Example 45
1133
1134		require.NoError(t, err)
1135
1136		for cursor.Next(context.Background()) {
1137			doc := cursor.Current
1138
1139			require.False(t, containsKey(doc, "_id"))
1140			require.True(t, containsKey(doc, "item"))
1141			require.True(t, containsKey(doc, "status"))
1142			require.False(t, containsKey(doc, "size"))
1143			require.False(t, containsKey(doc, "instock"))
1144		}
1145
1146		require.NoError(t, cursor.Err())
1147	}
1148
1149	{
1150		// Start Example 46
1151
1152		projection := bson.D{
1153			{"status", 0},
1154			{"instock", 0},
1155		}
1156
1157		cursor, err := coll.Find(
1158			context.Background(),
1159			bson.D{
1160				{"status", "A"},
1161			},
1162			options.Find().SetProjection(projection),
1163		)
1164
1165		// End Example 46
1166
1167		require.NoError(t, err)
1168
1169		for cursor.Next(context.Background()) {
1170			doc := cursor.Current
1171
1172			require.True(t, containsKey(doc, "_id"))
1173			require.True(t, containsKey(doc, "item"))
1174			require.False(t, containsKey(doc, "status"))
1175			require.True(t, containsKey(doc, "size"))
1176			require.False(t, containsKey(doc, "instock"))
1177		}
1178
1179		require.NoError(t, cursor.Err())
1180	}
1181
1182	{
1183		// Start Example 47
1184
1185		projection := bson.D{
1186			{"item", 1},
1187			{"status", 1},
1188			{"size.uom", 1},
1189		}
1190
1191		cursor, err := coll.Find(
1192			context.Background(),
1193			bson.D{
1194				{"status", "A"},
1195			},
1196			options.Find().SetProjection(projection),
1197		)
1198
1199		// End Example 47
1200
1201		require.NoError(t, err)
1202
1203		for cursor.Next(context.Background()) {
1204			doc := cursor.Current
1205
1206			require.True(t, containsKey(doc, "_id"))
1207			require.True(t, containsKey(doc, "item"))
1208			require.True(t, containsKey(doc, "status"))
1209			require.True(t, containsKey(doc, "size"))
1210			require.False(t, containsKey(doc, "instock"))
1211
1212			require.True(t, containsKey(doc, "size", "uom"))
1213			require.False(t, containsKey(doc, "size", "h"))
1214			require.False(t, containsKey(doc, "size", "w"))
1215
1216		}
1217
1218		require.NoError(t, cursor.Err())
1219	}
1220
1221	{
1222		// Start Example 48
1223
1224		projection := bson.D{
1225			{"size.uom", 0},
1226		}
1227
1228		cursor, err := coll.Find(
1229			context.Background(),
1230			bson.D{
1231				{"status", "A"},
1232			},
1233			options.Find().SetProjection(projection),
1234		)
1235
1236		// End Example 48
1237
1238		require.NoError(t, err)
1239
1240		for cursor.Next(context.Background()) {
1241			doc := cursor.Current
1242
1243			require.True(t, containsKey(doc, "_id"))
1244			require.True(t, containsKey(doc, "item"))
1245			require.True(t, containsKey(doc, "status"))
1246			require.True(t, containsKey(doc, "size"))
1247			require.True(t, containsKey(doc, "instock"))
1248
1249			require.False(t, containsKey(doc, "size", "uom"))
1250			require.True(t, containsKey(doc, "size", "h"))
1251			require.True(t, containsKey(doc, "size", "w"))
1252
1253		}
1254
1255		require.NoError(t, cursor.Err())
1256	}
1257
1258	{
1259		// Start Example 49
1260
1261		projection := bson.D{
1262			{"item", 1},
1263			{"status", 1},
1264			{"instock.qty", 1},
1265		}
1266
1267		cursor, err := coll.Find(
1268			context.Background(),
1269			bson.D{
1270				{"status", "A"},
1271			},
1272			options.Find().SetProjection(projection),
1273		)
1274
1275		// End Example 49
1276
1277		require.NoError(t, err)
1278
1279		for cursor.Next(context.Background()) {
1280			doc := cursor.Current
1281
1282			require.True(t, containsKey(doc, "_id"))
1283			require.True(t, containsKey(doc, "item"))
1284			require.True(t, containsKey(doc, "status"))
1285			require.False(t, containsKey(doc, "size"))
1286			require.True(t, containsKey(doc, "instock"))
1287
1288			instock, err := doc.LookupErr("instock")
1289			require.NoError(t, err)
1290
1291			vals, err := instock.Array().Values()
1292			require.NoError(t, err)
1293
1294			for _, val := range vals {
1295				require.Equal(t, bson.TypeEmbeddedDocument, val.Type)
1296				subdoc := val.Document()
1297				elems, err := subdoc.Elements()
1298				require.NoError(t, err)
1299
1300				require.Equal(t, 1, len(elems))
1301				_, err = subdoc.LookupErr("qty")
1302				require.NoError(t, err)
1303			}
1304		}
1305
1306		require.NoError(t, cursor.Err())
1307	}
1308
1309	{
1310		// Start Example 50
1311
1312		projection := bson.D{
1313			{"item", 1},
1314			{"status", 1},
1315			{"instock", bson.D{
1316				{"$slice", -1},
1317			}},
1318		}
1319
1320		cursor, err := coll.Find(
1321			context.Background(),
1322			bson.D{
1323				{"status", "A"},
1324			},
1325			options.Find().SetProjection(projection),
1326		)
1327
1328		// End Example 50
1329
1330		require.NoError(t, err)
1331
1332		for cursor.Next(context.Background()) {
1333			doc := cursor.Current
1334
1335			require.True(t, containsKey(doc, "_id"))
1336			require.True(t, containsKey(doc, "item"))
1337			require.True(t, containsKey(doc, "status"))
1338			require.False(t, containsKey(doc, "size"))
1339			require.True(t, containsKey(doc, "instock"))
1340
1341			instock, err := doc.LookupErr("instock")
1342			require.NoError(t, err)
1343			vals, err := instock.Array().Values()
1344			require.NoError(t, err)
1345			require.Equal(t, len(vals), 1)
1346		}
1347
1348		require.NoError(t, cursor.Err())
1349	}
1350}
1351
1352// UpdateExamples contains examples of update operations.
1353func UpdateExamples(t *testing.T, db *mongo.Database) {
1354	coll := db.Collection("inventory_update")
1355
1356	err := coll.Drop(context.Background())
1357	require.NoError(t, err)
1358
1359	{
1360		// Start Example 51
1361
1362		docs := []interface{}{
1363			bson.D{
1364				{"item", "canvas"},
1365				{"qty", 100},
1366				{"size", bson.D{
1367					{"h", 28},
1368					{"w", 35.5},
1369					{"uom", "cm"},
1370				}},
1371				{"status", "A"},
1372			},
1373			bson.D{
1374				{"item", "journal"},
1375				{"qty", 25},
1376				{"size", bson.D{
1377					{"h", 14},
1378					{"w", 21},
1379					{"uom", "cm"},
1380				}},
1381				{"status", "A"},
1382			},
1383			bson.D{
1384				{"item", "mat"},
1385				{"qty", 85},
1386				{"size", bson.D{
1387					{"h", 27.9},
1388					{"w", 35.5},
1389					{"uom", "cm"},
1390				}},
1391				{"status", "A"},
1392			},
1393			bson.D{
1394				{"item", "mousepad"},
1395				{"qty", 25},
1396				{"size", bson.D{
1397					{"h", 19},
1398					{"w", 22.85},
1399					{"uom", "in"},
1400				}},
1401				{"status", "P"},
1402			},
1403			bson.D{
1404				{"item", "notebook"},
1405				{"qty", 50},
1406				{"size", bson.D{
1407					{"h", 8.5},
1408					{"w", 11},
1409					{"uom", "in"},
1410				}},
1411				{"status", "P"},
1412			},
1413			bson.D{
1414				{"item", "paper"},
1415				{"qty", 100},
1416				{"size", bson.D{
1417					{"h", 8.5},
1418					{"w", 11},
1419					{"uom", "in"},
1420				}},
1421				{"status", "D"},
1422			},
1423			bson.D{
1424				{"item", "planner"},
1425				{"qty", 75},
1426				{"size", bson.D{
1427					{"h", 22.85},
1428					{"w", 30},
1429					{"uom", "cm"},
1430				}},
1431				{"status", "D"},
1432			},
1433			bson.D{
1434				{"item", "postcard"},
1435				{"qty", 45},
1436				{"size", bson.D{
1437					{"h", 10},
1438					{"w", 15.25},
1439					{"uom", "cm"},
1440				}},
1441				{"status", "A"},
1442			},
1443			bson.D{
1444				{"item", "sketchbook"},
1445				{"qty", 80},
1446				{"size", bson.D{
1447					{"h", 14},
1448					{"w", 21},
1449					{"uom", "cm"},
1450				}},
1451				{"status", "A"},
1452			},
1453			bson.D{
1454				{"item", "sketch pad"},
1455				{"qty", 95},
1456				{"size", bson.D{
1457					{"h", 22.85},
1458					{"w", 30.5},
1459					{"uom", "cm"},
1460				}},
1461				{"status", "A"},
1462			},
1463		}
1464
1465		result, err := coll.InsertMany(context.Background(), docs)
1466
1467		// End Example 51
1468
1469		require.NoError(t, err)
1470		require.Len(t, result.InsertedIDs, 10)
1471	}
1472
1473	{
1474		// Start Example 52
1475
1476		result, err := coll.UpdateOne(
1477			context.Background(),
1478			bson.D{
1479				{"item", "paper"},
1480			},
1481			bson.D{
1482				{"$set", bson.D{
1483					{"size.uom", "cm"},
1484					{"status", "P"},
1485				}},
1486				{"$currentDate", bson.D{
1487					{"lastModified", true},
1488				}},
1489			},
1490		)
1491
1492		// End Example 52
1493
1494		require.NoError(t, err)
1495		require.Equal(t, int64(1), result.MatchedCount)
1496		require.Equal(t, int64(1), result.ModifiedCount)
1497
1498		cursor, err := coll.Find(
1499			context.Background(),
1500			bson.D{
1501				{"item", "paper"},
1502			})
1503
1504		require.NoError(t, err)
1505
1506		for cursor.Next(context.Background()) {
1507			doc := cursor.Current
1508
1509			uom, err := doc.LookupErr("size", "uom")
1510			require.NoError(t, err)
1511			require.Equal(t, uom.StringValue(), "cm")
1512
1513			status, err := doc.LookupErr("status")
1514			require.NoError(t, err)
1515			require.Equal(t, status.StringValue(), "P")
1516
1517			require.True(t, containsKey(doc, "lastModified"))
1518		}
1519
1520		require.NoError(t, cursor.Err())
1521	}
1522
1523	{
1524		// Start Example 53
1525
1526		result, err := coll.UpdateMany(
1527			context.Background(),
1528			bson.D{
1529				{"qty", bson.D{
1530					{"$lt", 50},
1531				}},
1532			},
1533			bson.D{
1534				{"$set", bson.D{
1535					{"size.uom", "cm"},
1536					{"status", "P"},
1537				}},
1538				{"$currentDate", bson.D{
1539					{"lastModified", true},
1540				}},
1541			},
1542		)
1543
1544		// End Example 53
1545
1546		require.NoError(t, err)
1547		require.Equal(t, int64(3), result.MatchedCount)
1548		require.Equal(t, int64(3), result.ModifiedCount)
1549
1550		cursor, err := coll.Find(
1551			context.Background(),
1552			bson.D{
1553				{"qty", bson.D{
1554					{"$lt", 50},
1555				}},
1556			})
1557
1558		require.NoError(t, err)
1559
1560		for cursor.Next(context.Background()) {
1561			doc := cursor.Current
1562
1563			uom, err := doc.LookupErr("size", "uom")
1564			require.NoError(t, err)
1565			require.Equal(t, uom.StringValue(), "cm")
1566
1567			status, err := doc.LookupErr("status")
1568			require.NoError(t, err)
1569			require.Equal(t, status.StringValue(), "P")
1570
1571			require.True(t, containsKey(doc, "lastModified"))
1572		}
1573
1574		require.NoError(t, cursor.Err())
1575	}
1576
1577	{
1578		// Start Example 54
1579
1580		result, err := coll.ReplaceOne(
1581			context.Background(),
1582			bson.D{
1583				{"item", "paper"},
1584			},
1585			bson.D{
1586				{"item", "paper"},
1587				{"instock", bson.A{
1588					bson.D{
1589						{"warehouse", "A"},
1590						{"qty", 60},
1591					},
1592					bson.D{
1593						{"warehouse", "B"},
1594						{"qty", 40},
1595					},
1596				}},
1597			},
1598		)
1599
1600		// End Example 54
1601
1602		require.NoError(t, err)
1603		require.Equal(t, int64(1), result.MatchedCount)
1604		require.Equal(t, int64(1), result.ModifiedCount)
1605
1606		cursor, err := coll.Find(
1607			context.Background(),
1608			bson.D{
1609				{"item", "paper"},
1610			})
1611
1612		require.NoError(t, err)
1613
1614		for cursor.Next(context.Background()) {
1615			require.True(t, containsKey(cursor.Current, "_id"))
1616			require.True(t, containsKey(cursor.Current, "item"))
1617			require.True(t, containsKey(cursor.Current, "instock"))
1618
1619			instock, err := cursor.Current.LookupErr("instock")
1620			require.NoError(t, err)
1621			vals, err := instock.Array().Values()
1622			require.NoError(t, err)
1623			require.Equal(t, len(vals), 2)
1624
1625		}
1626
1627		require.NoError(t, cursor.Err())
1628	}
1629
1630}
1631
1632// DeleteExamples contains examples of delete operations.
1633func DeleteExamples(t *testing.T, db *mongo.Database) {
1634	coll := db.Collection("inventory_delete")
1635
1636	err := coll.Drop(context.Background())
1637	require.NoError(t, err)
1638
1639	{
1640		// Start Example 55
1641		docs := []interface{}{
1642			bson.D{
1643				{"item", "journal"},
1644				{"qty", 25},
1645				{"size", bson.D{
1646					{"h", 14},
1647					{"w", 21},
1648					{"uom", "cm"},
1649				}},
1650				{"status", "A"},
1651			},
1652			bson.D{
1653				{"item", "notebook"},
1654				{"qty", 50},
1655				{"size", bson.D{
1656					{"h", 8.5},
1657					{"w", 11},
1658					{"uom", "in"},
1659				}},
1660				{"status", "P"},
1661			},
1662			bson.D{
1663				{"item", "paper"},
1664				{"qty", 100},
1665				{"size", bson.D{
1666					{"h", 8.5},
1667					{"w", 11},
1668					{"uom", "in"},
1669				}},
1670				{"status", "D"},
1671			},
1672			bson.D{
1673				{"item", "planner"},
1674				{"qty", 75},
1675				{"size", bson.D{
1676					{"h", 22.85},
1677					{"w", 30},
1678					{"uom", "cm"},
1679				}},
1680				{"status", "D"},
1681			},
1682			bson.D{
1683				{"item", "postcard"},
1684				{"qty", 45},
1685				{"size", bson.D{
1686					{"h", 10},
1687					{"w", 15.25},
1688					{"uom", "cm"},
1689				}},
1690				{"status", "A"},
1691			},
1692		}
1693
1694		result, err := coll.InsertMany(context.Background(), docs)
1695
1696		// End Example 55
1697
1698		require.NoError(t, err)
1699		require.Len(t, result.InsertedIDs, 5)
1700	}
1701
1702	{
1703		// Start Example 57
1704
1705		result, err := coll.DeleteMany(
1706			context.Background(),
1707			bson.D{
1708				{"status", "A"},
1709			},
1710		)
1711
1712		// End Example 57
1713
1714		require.NoError(t, err)
1715		require.Equal(t, int64(2), result.DeletedCount)
1716	}
1717
1718	{
1719		// Start Example 58
1720
1721		result, err := coll.DeleteOne(
1722			context.Background(),
1723			bson.D{
1724				{"status", "D"},
1725			},
1726		)
1727
1728		// End Example 58
1729
1730		require.NoError(t, err)
1731		require.Equal(t, int64(1), result.DeletedCount)
1732
1733	}
1734
1735	{
1736		// Start Example 56
1737
1738		result, err := coll.DeleteMany(context.Background(), bson.D{})
1739
1740		// End Example 56
1741
1742		require.NoError(t, err)
1743		require.Equal(t, int64(2), result.DeletedCount)
1744	}
1745}
1746
1747var log = logger.New(ioutil.Discard, "", logger.LstdFlags)
1748
1749// Start Transactions Intro Example 1
1750
1751// UpdateEmployeeInfo is an example function demonstrating transactions.
1752func UpdateEmployeeInfo(ctx context.Context, client *mongo.Client) error {
1753	employees := client.Database("hr").Collection("employees")
1754	events := client.Database("reporting").Collection("events")
1755
1756	return client.UseSession(ctx, func(sctx mongo.SessionContext) error {
1757		err := sctx.StartTransaction(options.Transaction().
1758			SetReadConcern(readconcern.Snapshot()).
1759			SetWriteConcern(writeconcern.New(writeconcern.WMajority())),
1760		)
1761		if err != nil {
1762			return err
1763		}
1764
1765		_, err = employees.UpdateOne(sctx, bson.D{{"employee", 3}}, bson.D{{"$set", bson.D{{"status", "Inactive"}}}})
1766		if err != nil {
1767			sctx.AbortTransaction(sctx)
1768			log.Println("caught exception during transaction, aborting.")
1769			return err
1770		}
1771		_, err = events.InsertOne(sctx, bson.D{{"employee", 3}, {"status", bson.D{{"new", "Inactive"}, {"old", "Active"}}}})
1772		if err != nil {
1773			sctx.AbortTransaction(sctx)
1774			log.Println("caught exception during transaction, aborting.")
1775			return err
1776		}
1777
1778		for {
1779			err = sctx.CommitTransaction(sctx)
1780			switch e := err.(type) {
1781			case nil:
1782				return nil
1783			case mongo.CommandError:
1784				if e.HasErrorLabel("UnknownTransactionCommitResult") {
1785					log.Println("UnknownTransactionCommitResult, retrying commit operation...")
1786					continue
1787				}
1788				log.Println("Error during commit...")
1789				return e
1790			default:
1791				log.Println("Error during commit...")
1792				return e
1793			}
1794		}
1795	})
1796}
1797
1798// End Transactions Intro Example 1
1799
1800// Start Transactions Retry Example 1
1801
1802// RunTransactionWithRetry is an example function demonstrating transaction retry logic.
1803func RunTransactionWithRetry(sctx mongo.SessionContext, txnFn func(mongo.SessionContext) error) error {
1804	for {
1805		err := txnFn(sctx) // Performs transaction.
1806		if err == nil {
1807			return nil
1808		}
1809
1810		log.Println("Transaction aborted. Caught exception during transaction.")
1811
1812		// If transient error, retry the whole transaction
1813		if cmdErr, ok := err.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") {
1814			log.Println("TransientTransactionError, retrying transaction...")
1815			continue
1816		}
1817		return err
1818	}
1819}
1820
1821// End Transactions Retry Example 1
1822
1823// Start Transactions Retry Example 2
1824
1825// CommitWithRetry is an example function demonstrating transaction commit with retry logic.
1826func CommitWithRetry(sctx mongo.SessionContext) error {
1827	for {
1828		err := sctx.CommitTransaction(sctx)
1829		switch e := err.(type) {
1830		case nil:
1831			log.Println("Transaction committed.")
1832			return nil
1833		case mongo.CommandError:
1834			// Can retry commit
1835			if e.HasErrorLabel("UnknownTransactionCommitResult") {
1836				log.Println("UnknownTransactionCommitResult, retrying commit operation...")
1837				continue
1838			}
1839			log.Println("Error during commit...")
1840			return e
1841		default:
1842			log.Println("Error during commit...")
1843			return e
1844		}
1845	}
1846}
1847
1848// End Transactions Retry Example 2
1849
1850// TransactionsExamples contains examples for transaction operations.
1851func TransactionsExamples(ctx context.Context, client *mongo.Client) error {
1852	_, err := client.Database("hr").Collection("employees").InsertOne(ctx, bson.D{{"pi", 3.14159}})
1853	if err != nil {
1854		return err
1855	}
1856	_, err = client.Database("hr").Collection("employees").DeleteOne(ctx, bson.D{{"pi", 3.14159}})
1857	if err != nil {
1858		return err
1859	}
1860	_, err = client.Database("reporting").Collection("events").InsertOne(ctx, bson.D{{"pi", 3.14159}})
1861	if err != nil {
1862		return err
1863	}
1864	_, err = client.Database("reporting").Collection("events").DeleteOne(ctx, bson.D{{"pi", 3.14159}})
1865	if err != nil {
1866		return err
1867	}
1868	// Start Transactions Retry Example 3
1869
1870	runTransactionWithRetry := func(sctx mongo.SessionContext, txnFn func(mongo.SessionContext) error) error {
1871		for {
1872			err := txnFn(sctx) // Performs transaction.
1873			if err == nil {
1874				return nil
1875			}
1876
1877			log.Println("Transaction aborted. Caught exception during transaction.")
1878
1879			// If transient error, retry the whole transaction
1880			if cmdErr, ok := err.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") {
1881				log.Println("TransientTransactionError, retrying transaction...")
1882				continue
1883			}
1884			return err
1885		}
1886	}
1887
1888	commitWithRetry := func(sctx mongo.SessionContext) error {
1889		for {
1890			err := sctx.CommitTransaction(sctx)
1891			switch e := err.(type) {
1892			case nil:
1893				log.Println("Transaction committed.")
1894				return nil
1895			case mongo.CommandError:
1896				// Can retry commit
1897				if e.HasErrorLabel("UnknownTransactionCommitResult") {
1898					log.Println("UnknownTransactionCommitResult, retrying commit operation...")
1899					continue
1900				}
1901				log.Println("Error during commit...")
1902				return e
1903			default:
1904				log.Println("Error during commit...")
1905				return e
1906			}
1907		}
1908	}
1909
1910	// Updates two collections in a transaction.
1911	updateEmployeeInfo := func(sctx mongo.SessionContext) error {
1912		employees := client.Database("hr").Collection("employees")
1913		events := client.Database("reporting").Collection("events")
1914
1915		err := sctx.StartTransaction(options.Transaction().
1916			SetReadConcern(readconcern.Snapshot()).
1917			SetWriteConcern(writeconcern.New(writeconcern.WMajority())),
1918		)
1919		if err != nil {
1920			return err
1921		}
1922
1923		_, err = employees.UpdateOne(sctx, bson.D{{"employee", 3}}, bson.D{{"$set", bson.D{{"status", "Inactive"}}}})
1924		if err != nil {
1925			sctx.AbortTransaction(sctx)
1926			log.Println("caught exception during transaction, aborting.")
1927			return err
1928		}
1929		_, err = events.InsertOne(sctx, bson.D{{"employee", 3}, {"status", bson.D{{"new", "Inactive"}, {"old", "Active"}}}})
1930		if err != nil {
1931			sctx.AbortTransaction(sctx)
1932			log.Println("caught exception during transaction, aborting.")
1933			return err
1934		}
1935
1936		return commitWithRetry(sctx)
1937	}
1938
1939	return client.UseSessionWithOptions(
1940		ctx, options.Session().SetDefaultReadPreference(readpref.Primary()),
1941		func(sctx mongo.SessionContext) error {
1942			return runTransactionWithRetry(sctx, updateEmployeeInfo)
1943		},
1944	)
1945}
1946
1947// End Transactions Retry Example 3
1948
1949// Start Transactions withTxn API Example 1
1950
1951// WithTransactionExample is an example of using the Session.WithTransaction function.
1952func WithTransactionExample() {
1953	ctx := context.Background()
1954	// For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
1955	// uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl"
1956	// For a sharded cluster, connect to the mongos instances; e.g.
1957	// uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/"
1958	var uri string
1959
1960	clientOpts := options.Client().ApplyURI(uri)
1961	client, err := mongo.Connect(ctx, clientOpts)
1962	if err != nil {
1963		panic(err)
1964	}
1965	defer func() { _ = client.Disconnect(ctx) }()
1966
1967	// Prereq: Create collections.
1968	wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second))
1969	wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority)
1970	fooColl := client.Database("mydb1").Collection("foo", wcMajorityCollectionOpts)
1971	barColl := client.Database("mydb1").Collection("bar", wcMajorityCollectionOpts)
1972
1973	// Step 1: Define the callback that specifies the sequence of operations to perform inside the transaction.
1974	callback := func(sessCtx mongo.SessionContext) (interface{}, error) {
1975		// Important: You must pass sessCtx as the Context parameter to the operations for them to be executed in the
1976		// transaction.
1977		if _, err := fooColl.InsertOne(sessCtx, bson.D{{"abc", 1}}); err != nil {
1978			return nil, err
1979		}
1980		if _, err := barColl.InsertOne(sessCtx, bson.D{{"xyz", 999}}); err != nil {
1981			return nil, err
1982		}
1983
1984		return nil, nil
1985	}
1986
1987	// Step 2: Start a session and run the callback using WithTransaction.
1988	session, err := client.StartSession()
1989	if err != nil {
1990		panic(err)
1991	}
1992	defer session.EndSession(ctx)
1993
1994	result, err := session.WithTransaction(ctx, callback)
1995	if err != nil {
1996		panic(err)
1997	}
1998	fmt.Printf("result: %v\n", result)
1999}
2000
2001// End Transactions withTxn API Example 1
2002
2003// ChangeStreamExamples contains examples of changestream operations.
2004func ChangeStreamExamples(t *testing.T, db *mongo.Database) {
2005	ctx := context.Background()
2006
2007	coll := db.Collection("inventory_changestream")
2008
2009	err := coll.Drop(context.Background())
2010	require.NoError(t, err)
2011
2012	_, err = coll.InsertOne(ctx, bson.D{{"x", int32(1)}})
2013	require.NoError(t, err)
2014
2015	var stop int32
2016
2017	doInserts := func(coll *mongo.Collection) {
2018		for atomic.LoadInt32(&stop) == 0 {
2019			_, err = coll.InsertOne(ctx, bson.D{{"x", 1}})
2020			time.Sleep(10 * time.Millisecond)
2021			coll.DeleteOne(ctx, bson.D{{"x", 1}})
2022		}
2023	}
2024
2025	go doInserts(coll)
2026
2027	{
2028		// Start Changestream Example 1
2029
2030		cs, err := coll.Watch(ctx, mongo.Pipeline{})
2031		require.NoError(t, err)
2032		defer cs.Close(ctx)
2033
2034		ok := cs.Next(ctx)
2035		next := cs.Current
2036
2037		// End Changestream Example 1
2038
2039		require.True(t, ok)
2040		require.NoError(t, err)
2041		require.NotEqual(t, len(next), 0)
2042	}
2043	{
2044		// Start Changestream Example 2
2045
2046		cs, err := coll.Watch(ctx, mongo.Pipeline{}, options.ChangeStream().SetFullDocument(options.UpdateLookup))
2047		require.NoError(t, err)
2048		defer cs.Close(ctx)
2049
2050		ok := cs.Next(ctx)
2051		next := cs.Current
2052
2053		// End Changestream Example 2
2054
2055		require.True(t, ok)
2056		require.NoError(t, err)
2057		require.NotEqual(t, len(next), 0)
2058	}
2059
2060	{
2061		original, err := coll.Watch(ctx, mongo.Pipeline{})
2062		require.NoError(t, err)
2063		defer original.Close(ctx)
2064
2065		ok := original.Next(ctx)
2066		require.True(t, ok)
2067
2068		// Start Changestream Example 3
2069		resumeToken := original.ResumeToken()
2070
2071		cs, err := coll.Watch(ctx, mongo.Pipeline{}, options.ChangeStream().SetResumeAfter(resumeToken))
2072		require.NoError(t, err)
2073		defer cs.Close(ctx)
2074
2075		ok = cs.Next(ctx)
2076		result := cs.Current
2077
2078		// End Changestream Example 3
2079
2080		require.True(t, ok)
2081		require.NoError(t, err)
2082		require.NotEqual(t, len(result), 0)
2083	}
2084
2085	{
2086		// Start Changestream Example 4
2087		pipeline := mongo.Pipeline{bson.D{{"$match", bson.D{{"$or",
2088			bson.A{
2089				bson.D{{"fullDocument.username", "alice"}},
2090				bson.D{{"operationType", "delete"}}}}},
2091		}}}
2092		cs, err := coll.Watch(ctx, pipeline)
2093		require.NoError(t, err)
2094		defer cs.Close(ctx)
2095
2096		ok := cs.Next(ctx)
2097		next := cs.Current
2098
2099		// End Changestream Example 4
2100
2101		require.True(t, ok)
2102		require.NoError(t, err)
2103		require.NotEqual(t, len(next), 0)
2104	}
2105
2106	atomic.StoreInt32(&stop, 1)
2107}
2108
2109// AggregationExamples contains examples of aggregation operations.
2110func AggregationExamples(t *testing.T, db *mongo.Database) {
2111	ctx := context.Background()
2112
2113	salesColl := db.Collection("sales")
2114	airlinesColl := db.Collection("airlines")
2115	airAlliancesColl := db.Collection("air_alliances")
2116
2117	err := salesColl.Drop(ctx)
2118	require.NoError(t, err)
2119	err = airlinesColl.Drop(ctx)
2120	require.NoError(t, err)
2121	err = airAlliancesColl.Drop(ctx)
2122	require.NoError(t, err)
2123
2124	date20180208 := parseDate(t, "2018-02-08T09:00:00.000Z")
2125	date20180109 := parseDate(t, "2018-01-09T07:12:00.000Z")
2126	date20180127 := parseDate(t, "2018-01-27T09:13:00.000Z")
2127	date20180203 := parseDate(t, "2018-02-03T07:58:00.000Z")
2128	date20180205 := parseDate(t, "2018-02-05T06:03:00.000Z")
2129	date20180111 := parseDate(t, "2018-01-11T07:15:00.000Z")
2130
2131	sales := []interface{}{
2132		bson.D{
2133			{"date", date20180208},
2134			{"items", bson.A{
2135				bson.D{
2136					{"fruit", "kiwi"},
2137					{"quantity", 2},
2138					{"price", 0.5},
2139				},
2140				bson.D{
2141					{"fruit", "apple"},
2142					{"quantity", 1},
2143					{"price", 1.0},
2144				},
2145			}},
2146		},
2147		bson.D{
2148			{"date", date20180109},
2149			{"items", bson.A{
2150				bson.D{
2151					{"fruit", "banana"},
2152					{"quantity", 8},
2153					{"price", 1.0},
2154				},
2155				bson.D{
2156					{"fruit", "apple"},
2157					{"quantity", 1},
2158					{"price", 1.0},
2159				},
2160				bson.D{
2161					{"fruit", "papaya"},
2162					{"quantity", 1},
2163					{"price", 4.0},
2164				},
2165			}},
2166		},
2167		bson.D{
2168			{"date", date20180127},
2169			{"items", bson.A{
2170				bson.D{
2171					{"fruit", "banana"},
2172					{"quantity", 1},
2173					{"price", 1.0},
2174				},
2175			}},
2176		},
2177		bson.D{
2178			{"date", date20180203},
2179			{"items", bson.A{
2180				bson.D{
2181					{"fruit", "banana"},
2182					{"quantity", 1},
2183					{"price", 1.0},
2184				},
2185			}},
2186		},
2187		bson.D{
2188			{"date", date20180205},
2189			{"items", bson.A{
2190				bson.D{
2191					{"fruit", "banana"},
2192					{"quantity", 1},
2193					{"price", 1.0},
2194				},
2195				bson.D{
2196					{"fruit", "mango"},
2197					{"quantity", 2},
2198					{"price", 2.0},
2199				},
2200				bson.D{
2201					{"fruit", "apple"},
2202					{"quantity", 1},
2203					{"price", 1.0},
2204				},
2205			}},
2206		},
2207		bson.D{
2208			{"date", date20180111},
2209			{"items", bson.A{
2210				bson.D{
2211					{"fruit", "banana"},
2212					{"quantity", 1},
2213					{"price", 1.0},
2214				},
2215				bson.D{
2216					{"fruit", "apple"},
2217					{"quantity", 1},
2218					{"price", 1.0},
2219				},
2220				bson.D{
2221					{"fruit", "papaya"},
2222					{"quantity", 3},
2223					{"price", 4.0},
2224				},
2225			}},
2226		},
2227	}
2228	airlines := []interface{}{
2229		bson.D{
2230			{"airline", 17},
2231			{"name", "Air Canada"},
2232			{"alias", "AC"},
2233			{"iata", "ACA"},
2234			{"icao", "AIR CANADA"},
2235			{"active", "Y"},
2236			{"country", "Canada"},
2237			{"base", "TAL"},
2238		},
2239		bson.D{
2240			{"airline", 18},
2241			{"name", "Turkish Airlines"},
2242			{"alias", "YK"},
2243			{"iata", "TRK"},
2244			{"icao", "TURKISH"},
2245			{"active", "Y"},
2246			{"country", "Turkey"},
2247			{"base", "AET"},
2248		},
2249		bson.D{
2250			{"airline", 22},
2251			{"name", "Saudia"},
2252			{"alias", "SV"},
2253			{"iata", "SVA"},
2254			{"icao", "SAUDIA"},
2255			{"active", "Y"},
2256			{"country", "Saudi Arabia"},
2257			{"base", "JSU"},
2258		},
2259		bson.D{
2260			{"airline", 29},
2261			{"name", "Finnair"},
2262			{"alias", "AY"},
2263			{"iata", "FIN"},
2264			{"icao", "FINNAIR"},
2265			{"active", "Y"},
2266			{"country", "Finland"},
2267			{"base", "JMZ"},
2268		},
2269		bson.D{
2270			{"airline", 34},
2271			{"name", "Afric'air Express"},
2272			{"alias", ""},
2273			{"iata", "AAX"},
2274			{"icao", "AFREX"},
2275			{"active", "N"},
2276			{"country", "Ivory Coast"},
2277			{"base", "LOK"},
2278		},
2279		bson.D{
2280			{"airline", 37},
2281			{"name", "Artem-Avia"},
2282			{"alias", ""},
2283			{"iata", "ABA"},
2284			{"icao", "ARTEM-AVIA"},
2285			{"active", "N"},
2286			{"country", "Ukraine"},
2287			{"base", "JBR"},
2288		},
2289		bson.D{
2290			{"airline", 38},
2291			{"name", "Lufthansa"},
2292			{"alias", "LH"},
2293			{"iata", "DLH"},
2294			{"icao", "LUFTHANSA"},
2295			{"active", "Y"},
2296			{"country", "Germany"},
2297			{"base", "CYS"},
2298		},
2299	}
2300	airAlliances := []interface{}{
2301		bson.D{
2302			{"name", "Star Alliance"},
2303			{"airlines", bson.A{
2304				"Air Canada",
2305				"Avianca",
2306				"Air China",
2307				"Air New Zealand",
2308				"Asiana Airlines",
2309				"Brussels Airlines",
2310				"Copa Airlines",
2311				"Croatia Airlines",
2312				"EgyptAir",
2313				"TAP Portugal",
2314				"United Airlines",
2315				"Turkish Airlines",
2316				"Swiss International Air Lines",
2317				"Lufthansa",
2318			}},
2319		},
2320		bson.D{
2321			{"name", "SkyTeam"},
2322			{"airlines", bson.A{
2323				"Aerolinias Argentinas",
2324				"Aeromexico",
2325				"Air Europa",
2326				"Air France",
2327				"Alitalia",
2328				"Delta Air Lines",
2329				"Garuda Indonesia",
2330				"Kenya Airways",
2331				"KLM",
2332				"Korean Air",
2333				"Middle East Airlines",
2334				"Saudia",
2335			}},
2336		},
2337		bson.D{
2338			{"name", "OneWorld"},
2339			{"airlines", bson.A{
2340				"Air Berlin",
2341				"American Airlines",
2342				"British Airways",
2343				"Cathay Pacific",
2344				"Finnair",
2345				"Iberia Airlines",
2346				"Japan Airlines",
2347				"LATAM Chile",
2348				"LATAM Brasil",
2349				"Malasya Airlines",
2350				"Canadian Airlines",
2351			}},
2352		},
2353	}
2354
2355	salesResult, salesErr := salesColl.InsertMany(ctx, sales)
2356	airlinesResult, airlinesErr := airlinesColl.InsertMany(ctx, airlines)
2357	airAlliancesResult, airAlliancesErr := airAlliancesColl.InsertMany(ctx, airAlliances)
2358
2359	require.NoError(t, salesErr)
2360	require.Len(t, salesResult.InsertedIDs, 6)
2361	require.NoError(t, airlinesErr)
2362	require.Len(t, airlinesResult.InsertedIDs, 7)
2363	require.NoError(t, airAlliancesErr)
2364	require.Len(t, airAlliancesResult.InsertedIDs, 3)
2365
2366	{
2367		// Start Aggregation Example 1
2368		pipeline := mongo.Pipeline{
2369			{
2370				{"$match", bson.D{
2371					{"items.fruit", "banana"},
2372				}},
2373			},
2374			{
2375				{"$sort", bson.D{
2376					{"date", 1},
2377				}},
2378			},
2379		}
2380
2381		cursor, err := salesColl.Aggregate(ctx, pipeline)
2382
2383		// End Aggregation Example 1
2384
2385		require.NoError(t, err)
2386		defer cursor.Close(ctx)
2387		requireCursorLength(t, cursor, 5)
2388	}
2389	{
2390		// Start Aggregation Example 2
2391		pipeline := mongo.Pipeline{
2392			{
2393				{"$unwind", "$items"},
2394			},
2395			{
2396				{"$match", bson.D{
2397					{"items.fruit", "banana"},
2398				}},
2399			},
2400			{
2401				{"$group", bson.D{
2402					{"_id", bson.D{
2403						{"day", bson.D{
2404							{"$dayOfWeek", "$date"},
2405						}},
2406					}},
2407					{"count", bson.D{
2408						{"$sum", "$items.quantity"},
2409					}},
2410				}},
2411			},
2412			{
2413				{"$project", bson.D{
2414					{"dayOfWeek", "$_id.day"},
2415					{"numberSold", "$count"},
2416					{"_id", 0},
2417				}},
2418			},
2419			{
2420				{"$sort", bson.D{
2421					{"numberSold", 1},
2422				}},
2423			},
2424		}
2425
2426		cursor, err := salesColl.Aggregate(ctx, pipeline)
2427
2428		// End Aggregation Example 2
2429
2430		require.NoError(t, err)
2431		defer cursor.Close(ctx)
2432		requireCursorLength(t, cursor, 4)
2433	}
2434	{
2435		// Start Aggregation Example 3
2436		pipeline := mongo.Pipeline{
2437			{
2438				{"$unwind", "$items"},
2439			},
2440			{
2441				{"$group", bson.D{
2442					{"_id", bson.D{
2443						{"day", bson.D{
2444							{"$dayOfWeek", "$date"},
2445						}},
2446					}},
2447					{"items_sold", bson.D{
2448						{"$sum", "$items.quantity"},
2449					}},
2450					{"revenue", bson.D{
2451						{"$sum", bson.D{
2452							{"$multiply", bson.A{"$items.quantity", "$items.price"}},
2453						}},
2454					}},
2455				}},
2456			},
2457			{
2458				{"$project", bson.D{
2459					{"day", "$_id.day"},
2460					{"revenue", 1},
2461					{"items_sold", 1},
2462					{"discount", bson.D{
2463						{"$cond", bson.D{
2464							{"if", bson.D{
2465								{"$lte", bson.A{"$revenue", 250}},
2466							}},
2467							{"then", 25},
2468							{"else", 0},
2469						}},
2470					}},
2471				}},
2472			},
2473		}
2474
2475		cursor, err := salesColl.Aggregate(ctx, pipeline)
2476
2477		// End Aggregation Example 3
2478
2479		require.NoError(t, err)
2480		defer cursor.Close(ctx)
2481		requireCursorLength(t, cursor, 4)
2482	}
2483	{
2484		// Start Aggregation Example 4
2485		pipeline := mongo.Pipeline{
2486			{
2487				{"$lookup", bson.D{
2488					{"from", "air_airlines"},
2489					{"let", bson.D{
2490						{"constituents", "$airlines"}},
2491					},
2492					{"pipeline", bson.A{bson.D{
2493						{"$match", bson.D{
2494							{"$expr", bson.D{
2495								{"$in", bson.A{"$name", "$$constituents"}},
2496							}},
2497						}},
2498					}}},
2499					{"as", "airlines"},
2500				}},
2501			},
2502			{
2503				{"$project", bson.D{
2504					{"_id", 0},
2505					{"name", 1},
2506					{"airlines", bson.D{
2507						{"$filter", bson.D{
2508							{"input", "$airlines"},
2509							{"as", "airline"},
2510							{"cond", bson.D{
2511								{"$eq", bson.A{"$$airline.country", "Canada"}},
2512							}},
2513						}},
2514					}},
2515				}},
2516			},
2517		}
2518
2519		cursor, err := airAlliancesColl.Aggregate(ctx, pipeline)
2520
2521		// End Aggregation Example 4
2522
2523		require.NoError(t, err)
2524		defer cursor.Close(ctx)
2525		requireCursorLength(t, cursor, 3)
2526	}
2527}
2528
2529// RunCommandExamples contains examples of RunCommand operations.
2530func RunCommandExamples(t *testing.T, db *mongo.Database) {
2531	ctx := context.Background()
2532
2533	coll := db.Collection("restaurants")
2534
2535	err := coll.Drop(ctx)
2536	require.NoError(t, err)
2537
2538	restaurants := []interface{}{
2539		bson.D{
2540			{"name", "Chez Panisse"},
2541			{"city", "Oakland"},
2542			{"state", "California"},
2543			{"country", "United States"},
2544			{"rating", 4.4},
2545		},
2546		bson.D{
2547			{"name", "Central"},
2548			{"city", "Lima"},
2549			{"country", "Peru"},
2550			{"rating", 4.8},
2551		},
2552		bson.D{
2553			{"name", "Eleven Madison Park"},
2554			{"city", "New York City"},
2555			{"state", "New York"},
2556			{"country", "United States"},
2557			{"rating", 4.6},
2558		},
2559		bson.D{
2560			{"name", "Gaggan"},
2561			{"city", "Bangkok"},
2562			{"country", "Thailand"},
2563			{"rating", 4.3},
2564		},
2565		bson.D{
2566			{"name", "Dad's Grill"},
2567			{"city", "Oklahoma City"},
2568			{"state", "Oklahoma"},
2569			{"country", "United States"},
2570			{"rating", 2.1},
2571		},
2572	}
2573
2574	result, err := coll.InsertMany(ctx, restaurants)
2575	require.NoError(t, err)
2576	require.Len(t, result.InsertedIDs, 5)
2577
2578	{
2579		// Start RunCommand Example 1
2580		res := db.RunCommand(ctx, bson.D{{"buildInfo", 1}})
2581
2582		// End RunCommand Example 1
2583
2584		err := res.Err()
2585		require.NoError(t, err)
2586	}
2587	{
2588		// Start RunCommand Example 2
2589		res := db.RunCommand(ctx, bson.D{{"collStats", "restaurants"}})
2590
2591		// End RunCommand Example 2
2592
2593		err := res.Err()
2594		require.NoError(t, err)
2595	}
2596}
2597
2598// IndexExamples contains examples of Index operations.
2599func IndexExamples(t *testing.T, db *mongo.Database) {
2600	ctx := context.Background()
2601
2602	recordsColl := db.Collection("records")
2603	restaurantsColl := db.Collection("restaurants")
2604
2605	err := recordsColl.Drop(ctx)
2606	require.NoError(t, err)
2607	err = restaurantsColl.Drop(ctx)
2608	require.NoError(t, err)
2609
2610	records := []interface{}{
2611		bson.D{
2612			{"student", "Marty McFly"},
2613			{"classYear", 1986},
2614			{"school", "Hill Valley High"},
2615			{"score", 56.5},
2616		},
2617		bson.D{
2618			{"student", "Ferris F. Bueller"},
2619			{"classYear", 1987},
2620			{"school", "Glenbrook North High"},
2621			{"status", "Suspended"},
2622			{"score", 76.0},
2623		},
2624		bson.D{
2625			{"student", "Reynard Muldoon"},
2626			{"classYear", 2007},
2627			{"school", "Stonetown Middle"},
2628			{"score", 99.9},
2629		},
2630	}
2631	restaurants := []interface{}{
2632		bson.D{
2633			{"name", "Chez Panisse"},
2634			{"cuisine", "American/French"},
2635			{"city", "Oakland"},
2636			{"state", "California"},
2637			{"country", "United States"},
2638			{"rating", 4.9},
2639		},
2640		bson.D{
2641			{"name", "Central"},
2642			{"cuisine", "Peruvian"},
2643			{"city", "Lima"},
2644			{"country", "Peru"},
2645			{"rating", 5.8},
2646		},
2647		bson.D{
2648			{"name", "Eleven Madison Park"},
2649			{"cuisine", "French"},
2650			{"city", "New York City"},
2651			{"state", "New York"},
2652			{"country", "United States"},
2653			{"rating", 7.1},
2654		},
2655		bson.D{
2656			{"name", "Gaggan"},
2657			{"cuisine", "Thai Fusion"},
2658			{"city", "Bangkok"},
2659			{"country", "Thailand"},
2660			{"rating", 9.2},
2661		},
2662		bson.D{
2663			{"name", "Dad's Grill"},
2664			{"cuisine", "BBQ"},
2665			{"city", "Oklahoma City"},
2666			{"state", "Oklahoma"},
2667			{"country", "United States"},
2668			{"rating", 2.1},
2669		},
2670	}
2671
2672	recordsResult, recordsErr := recordsColl.InsertMany(ctx, records)
2673	restaurantsResult, restaurantsErr := restaurantsColl.InsertMany(ctx, restaurants)
2674
2675	require.NoError(t, recordsErr)
2676	require.Len(t, recordsResult.InsertedIDs, 3)
2677	require.NoError(t, restaurantsErr)
2678	require.Len(t, restaurantsResult.InsertedIDs, 5)
2679
2680	{
2681		// Start Index Example 1
2682		indexModel := mongo.IndexModel{
2683			Keys: bson.D{
2684				{"score", 1},
2685			},
2686		}
2687		_, err := recordsColl.Indexes().CreateOne(ctx, indexModel)
2688
2689		// End Index Example 1
2690
2691		require.NoError(t, err)
2692	}
2693	{
2694		// Start Index Example 2
2695		partialFilterExpression := bson.D{
2696			{"rating", bson.D{
2697				{"$gt", 5},
2698			}},
2699		}
2700		indexModel := mongo.IndexModel{
2701			Keys: bson.D{
2702				{"cuisine", 1},
2703				{"name", 1},
2704			},
2705			Options: options.Index().SetPartialFilterExpression(partialFilterExpression),
2706		}
2707
2708		_, err := restaurantsColl.Indexes().CreateOne(ctx, indexModel)
2709
2710		// End Index Example 2
2711
2712		require.NoError(t, err)
2713	}
2714}
2715