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
49// InsertExamples contains examples for insert operations.
50func InsertExamples(t *testing.T, db *mongo.Database) {
51	coll := db.Collection("inventory_insert")
52
53	err := coll.Drop(context.Background())
54	require.NoError(t, err)
55
56	{
57		// Start Example 1
58
59		result, err := coll.InsertOne(
60			context.Background(),
61			bson.D{
62				{"item", "canvas"},
63				{"qty", 100},
64				{"tags", bson.A{"cotton"}},
65				{"size", bson.D{
66					{"h", 28},
67					{"w", 35.5},
68					{"uom", "cm"},
69				}},
70			})
71
72		// End Example 1
73
74		require.NoError(t, err)
75		require.NotNil(t, result.InsertedID)
76	}
77
78	{
79		// Start Example 2
80
81		cursor, err := coll.Find(
82			context.Background(),
83			bson.D{{"item", "canvas"}},
84		)
85
86		// End Example 2
87
88		require.NoError(t, err)
89		requireCursorLength(t, cursor, 1)
90
91	}
92
93	{
94		// Start Example 3
95
96		result, err := coll.InsertMany(
97			context.Background(),
98			[]interface{}{
99				bson.D{
100					{"item", "journal"},
101					{"qty", int32(25)},
102					{"tags", bson.A{"blank", "red"}},
103					{"size", bson.D{
104						{"h", 14},
105						{"w", 21},
106						{"uom", "cm"},
107					}},
108				},
109				bson.D{
110					{"item", "mat"},
111					{"qty", int32(25)},
112					{"tags", bson.A{"gray"}},
113					{"size", bson.D{
114						{"h", 27.9},
115						{"w", 35.5},
116						{"uom", "cm"},
117					}},
118				},
119				bson.D{
120					{"item", "mousepad"},
121					{"qty", 25},
122					{"tags", bson.A{"gel", "blue"}},
123					{"size", bson.D{
124						{"h", 19},
125						{"w", 22.85},
126						{"uom", "cm"},
127					}},
128				},
129			})
130
131		// End Example 3
132
133		require.NoError(t, err)
134		require.Len(t, result.InsertedIDs, 3)
135	}
136}
137
138// QueryToplevelFieldsExamples contains examples for querying top-level fields.
139func QueryToplevelFieldsExamples(t *testing.T, db *mongo.Database) {
140	coll := db.Collection("inventory_query_top")
141
142	err := coll.Drop(context.Background())
143	require.NoError(t, err)
144
145	{
146		// Start Example 6
147
148		docs := []interface{}{
149			bson.D{
150				{"item", "journal"},
151				{"qty", 25},
152				{"size", bson.D{
153					{"h", 14},
154					{"w", 21},
155					{"uom", "cm"},
156				}},
157				{"status", "A"},
158			},
159			bson.D{
160				{"item", "notebook"},
161				{"qty", 50},
162				{"size", bson.D{
163					{"h", 8.5},
164					{"w", 11},
165					{"uom", "in"},
166				}},
167				{"status", "A"},
168			},
169			bson.D{
170				{"item", "paper"},
171				{"qty", 100},
172				{"size", bson.D{
173					{"h", 8.5},
174					{"w", 11},
175					{"uom", "in"},
176				}},
177				{"status", "D"},
178			},
179			bson.D{
180				{"item", "planner"},
181				{"qty", 75},
182				{"size", bson.D{
183					{"h", 22.85},
184					{"w", 30},
185					{"uom", "cm"},
186				}},
187				{"status", "D"},
188			},
189			bson.D{
190				{"item", "postcard"},
191				{"qty", 45},
192				{"size", bson.D{
193					{"h", 10},
194					{"w", 15.25},
195					{"uom", "cm"},
196				}},
197				{"status", "A"},
198			},
199		}
200
201		result, err := coll.InsertMany(context.Background(), docs)
202
203		// End Example 6
204
205		require.NoError(t, err)
206		require.Len(t, result.InsertedIDs, 5)
207	}
208
209	{
210		// Start Example 7
211
212		cursor, err := coll.Find(
213			context.Background(),
214			bson.D{},
215		)
216
217		// End Example 7
218
219		require.NoError(t, err)
220		requireCursorLength(t, cursor, 5)
221	}
222
223	{
224		// Start Example 9
225
226		cursor, err := coll.Find(
227			context.Background(),
228			bson.D{{"status", "D"}},
229		)
230
231		// End Example 9
232
233		require.NoError(t, err)
234		requireCursorLength(t, cursor, 2)
235	}
236
237	{
238		// Start Example 10
239
240		cursor, err := coll.Find(
241			context.Background(),
242			bson.D{{"status", bson.D{{"$in", bson.A{"A", "D"}}}}})
243
244		// End Example 10
245
246		require.NoError(t, err)
247		requireCursorLength(t, cursor, 5)
248	}
249
250	{
251		// Start Example 11
252
253		cursor, err := coll.Find(
254			context.Background(),
255			bson.D{
256				{"status", "A"},
257				{"qty", bson.D{{"$lt", 30}}},
258			})
259
260		// End Example 11
261
262		require.NoError(t, err)
263		requireCursorLength(t, cursor, 1)
264	}
265
266	{
267		// Start Example 12
268
269		cursor, err := coll.Find(
270			context.Background(),
271			bson.D{
272				{"$or",
273					bson.A{
274						bson.D{{"status", "A"}},
275						bson.D{{"qty", bson.D{{"$lt", 30}}}},
276					}},
277			})
278
279		// End Example 12
280
281		require.NoError(t, err)
282		requireCursorLength(t, cursor, 3)
283	}
284
285	{
286		// Start Example 13
287
288		cursor, err := coll.Find(
289			context.Background(),
290			bson.D{
291				{"status", "A"},
292				{"$or", bson.A{
293					bson.D{{"qty", bson.D{{"$lt", 30}}}},
294					bson.D{{"item", primitive.Regex{Pattern: "^p", Options: ""}}},
295				}},
296			})
297
298		// End Example 13
299
300		require.NoError(t, err)
301		requireCursorLength(t, cursor, 2)
302	}
303
304}
305
306// QueryEmbeddedDocumentsExamples contains examples for querying embedded document fields.
307func QueryEmbeddedDocumentsExamples(t *testing.T, db *mongo.Database) {
308	coll := db.Collection("inventory_query_embedded")
309
310	err := coll.Drop(context.Background())
311	require.NoError(t, err)
312
313	{
314		// Start Example 14
315
316		docs := []interface{}{
317			bson.D{
318				{"item", "journal"},
319				{"qty", 25},
320				{"size", bson.D{
321					{"h", 14},
322					{"w", 21},
323					{"uom", "cm"},
324				}},
325				{"status", "A"},
326			},
327			bson.D{
328				{"item", "notebook"},
329				{"qty", 50},
330				{"size", bson.D{
331					{"h", 8.5},
332					{"w", 11},
333					{"uom", "in"},
334				}},
335				{"status", "A"},
336			},
337			bson.D{
338				{"item", "paper"},
339				{"qty", 100},
340				{"size", bson.D{
341					{"h", 8.5},
342					{"w", 11},
343					{"uom", "in"},
344				}},
345				{"status", "D"},
346			},
347			bson.D{
348				{"item", "planner"},
349				{"qty", 75},
350				{"size", bson.D{
351					{"h", 22.85},
352					{"w", 30},
353					{"uom", "cm"},
354				}},
355				{"status", "D"},
356			},
357			bson.D{
358				{"item", "postcard"},
359				{"qty", 45},
360				{"size", bson.D{
361					{"h", 10},
362					{"w", 15.25},
363					{"uom", "cm"},
364				}},
365				{"status", "A"},
366			},
367		}
368
369		result, err := coll.InsertMany(context.Background(), docs)
370
371		// End Example 14
372
373		require.NoError(t, err)
374		require.Len(t, result.InsertedIDs, 5)
375	}
376
377	{
378		// Start Example 15
379
380		cursor, err := coll.Find(
381			context.Background(),
382			bson.D{
383				{"size", bson.D{
384					{"h", 14},
385					{"w", 21},
386					{"uom", "cm"},
387				}},
388			})
389
390		// End Example 15
391
392		require.NoError(t, err)
393		requireCursorLength(t, cursor, 1)
394	}
395
396	{
397		// Start Example 16
398
399		cursor, err := coll.Find(
400			context.Background(),
401			bson.D{
402				{"size", bson.D{
403					{"w", 21},
404					{"h", 14},
405					{"uom", "cm"},
406				}},
407			})
408
409		// End Example 16
410
411		require.NoError(t, err)
412		requireCursorLength(t, cursor, 0)
413	}
414
415	{
416		// Start Example 17
417
418		cursor, err := coll.Find(
419			context.Background(),
420			bson.D{{"size.uom", "in"}},
421		)
422
423		// End Example 17
424
425		require.NoError(t, err)
426		requireCursorLength(t, cursor, 2)
427	}
428
429	{
430		// Start Example 18
431
432		cursor, err := coll.Find(
433			context.Background(),
434			bson.D{
435				{"size.h", bson.D{
436					{"$lt", 15},
437				}},
438			})
439
440		// End Example 18
441
442		require.NoError(t, err)
443		requireCursorLength(t, cursor, 4)
444	}
445
446	{
447		// Start Example 19
448
449		cursor, err := coll.Find(
450			context.Background(),
451			bson.D{
452				{"size.h", bson.D{
453					{"$lt", 15},
454				}},
455				{"size.uom", "in"},
456				{"status", "D"},
457			})
458
459		// End Example 19
460
461		require.NoError(t, err)
462		requireCursorLength(t, cursor, 1)
463	}
464
465}
466
467// QueryArraysExamples contains examples for querying array fields.
468func QueryArraysExamples(t *testing.T, db *mongo.Database) {
469	coll := db.Collection("inventory_query_array")
470
471	err := coll.Drop(context.Background())
472	require.NoError(t, err)
473
474	{
475		// Start Example 20
476
477		docs := []interface{}{
478			bson.D{
479				{"item", "journal"},
480				{"qty", 25},
481				{"tags", bson.A{"blank", "red"}},
482				{"dim_cm", bson.A{14, 21}},
483			},
484			bson.D{
485				{"item", "notebook"},
486				{"qty", 50},
487				{"tags", bson.A{"red", "blank"}},
488				{"dim_cm", bson.A{14, 21}},
489			},
490			bson.D{
491				{"item", "paper"},
492				{"qty", 100},
493				{"tags", bson.A{"red", "blank", "plain"}},
494				{"dim_cm", bson.A{14, 21}},
495			},
496			bson.D{
497				{"item", "planner"},
498				{"qty", 75},
499				{"tags", bson.A{"blank", "red"}},
500				{"dim_cm", bson.A{22.85, 30}},
501			},
502			bson.D{
503				{"item", "postcard"},
504				{"qty", 45},
505				{"tags", bson.A{"blue"}},
506				{"dim_cm", bson.A{10, 15.25}},
507			},
508		}
509
510		result, err := coll.InsertMany(context.Background(), docs)
511
512		// End Example 20
513
514		require.NoError(t, err)
515		require.Len(t, result.InsertedIDs, 5)
516	}
517
518	{
519		// Start Example 21
520
521		cursor, err := coll.Find(
522			context.Background(),
523			bson.D{{"tags", bson.A{"red", "blank"}}},
524		)
525
526		// End Example 21
527
528		require.NoError(t, err)
529		requireCursorLength(t, cursor, 1)
530	}
531
532	{
533		// Start Example 22
534
535		cursor, err := coll.Find(
536			context.Background(),
537			bson.D{
538				{"tags", bson.D{{"$all", bson.A{"red", "blank"}}}},
539			})
540
541		// End Example 22
542
543		require.NoError(t, err)
544		requireCursorLength(t, cursor, 4)
545	}
546
547	{
548		// Start Example 23
549
550		cursor, err := coll.Find(
551			context.Background(),
552			bson.D{
553				{"tags", "red"},
554			})
555
556		// End Example 23
557
558		require.NoError(t, err)
559		requireCursorLength(t, cursor, 4)
560	}
561
562	{
563		// Start Example 24
564
565		cursor, err := coll.Find(
566			context.Background(),
567			bson.D{
568				{"dim_cm", bson.D{
569					{"$gt", 25},
570				}},
571			})
572
573		// End Example 24
574
575		require.NoError(t, err)
576		requireCursorLength(t, cursor, 1)
577	}
578
579	{
580		// Start Example 25
581
582		cursor, err := coll.Find(
583			context.Background(),
584			bson.D{
585				{"dim_cm", bson.D{
586					{"$gt", 15},
587					{"$lt", 20},
588				}},
589			})
590
591		// End Example 25
592
593		require.NoError(t, err)
594		requireCursorLength(t, cursor, 4)
595	}
596
597	{
598		// Start Example 26
599
600		cursor, err := coll.Find(
601			context.Background(),
602			bson.D{
603				{"dim_cm", bson.D{
604					{"$elemMatch", bson.D{
605						{"$gt", 22},
606						{"$lt", 30},
607					}},
608				}},
609			})
610
611		// End Example 26
612
613		require.NoError(t, err)
614		requireCursorLength(t, cursor, 1)
615	}
616
617	{
618		// Start Example 27
619
620		cursor, err := coll.Find(
621			context.Background(),
622			bson.D{
623				{"dim_cm.1", bson.D{
624					{"$gt", 25},
625				}},
626			})
627
628		// End Example 27
629
630		require.NoError(t, err)
631		requireCursorLength(t, cursor, 1)
632	}
633
634	{
635		// Start Example 28
636
637		cursor, err := coll.Find(
638			context.Background(),
639			bson.D{
640				{"tags", bson.D{
641					{"$size", 3},
642				}},
643			})
644
645		// End Example 28
646
647		require.NoError(t, err)
648		requireCursorLength(t, cursor, 1)
649	}
650
651}
652
653// QueryArrayEmbeddedDocumentsExamples contains examples for querying fields with arrays and embedded documents.
654func QueryArrayEmbeddedDocumentsExamples(t *testing.T, db *mongo.Database) {
655	coll := db.Collection("inventory_query_array_embedded")
656
657	err := coll.Drop(context.Background())
658	require.NoError(t, err)
659
660	{
661		// Start Example 29
662
663		docs := []interface{}{
664			bson.D{
665				{"item", "journal"},
666				{"instock", bson.A{
667					bson.D{
668						{"warehouse", "A"},
669						{"qty", 5},
670					},
671					bson.D{
672						{"warehouse", "C"},
673						{"qty", 15},
674					},
675				}},
676			},
677			bson.D{
678				{"item", "notebook"},
679				{"instock", bson.A{
680					bson.D{
681						{"warehouse", "C"},
682						{"qty", 5},
683					},
684				}},
685			},
686			bson.D{
687				{"item", "paper"},
688				{"instock", bson.A{
689					bson.D{
690						{"warehouse", "A"},
691						{"qty", 60},
692					},
693					bson.D{
694						{"warehouse", "B"},
695						{"qty", 15},
696					},
697				}},
698			},
699			bson.D{
700				{"item", "planner"},
701				{"instock", bson.A{
702					bson.D{
703						{"warehouse", "A"},
704						{"qty", 40},
705					},
706					bson.D{
707						{"warehouse", "B"},
708						{"qty", 5},
709					},
710				}},
711			},
712			bson.D{
713				{"item", "postcard"},
714				{"instock", bson.A{
715					bson.D{
716						{"warehouse", "B"},
717						{"qty", 15},
718					},
719					bson.D{
720						{"warehouse", "C"},
721						{"qty", 35},
722					},
723				}},
724			},
725		}
726
727		result, err := coll.InsertMany(context.Background(), docs)
728
729		// End Example 29
730
731		require.NoError(t, err)
732		require.Len(t, result.InsertedIDs, 5)
733	}
734
735	{
736		// Start Example 30
737
738		cursor, err := coll.Find(
739			context.Background(),
740			bson.D{
741				{"instock", bson.D{
742					{"warehouse", "A"},
743					{"qty", 5},
744				}},
745			})
746
747		// End Example 30
748
749		require.NoError(t, err)
750		requireCursorLength(t, cursor, 1)
751	}
752
753	{
754		// Start Example 31
755
756		cursor, err := coll.Find(
757			context.Background(),
758			bson.D{
759				{"instock", bson.D{
760					{"qty", 5},
761					{"warehouse", "A"},
762				}},
763			})
764
765		// End Example 31
766
767		require.NoError(t, err)
768		requireCursorLength(t, cursor, 0)
769	}
770
771	{
772		// Start Example 32
773
774		cursor, err := coll.Find(
775			context.Background(),
776			bson.D{
777				{"instock.0.qty", bson.D{
778					{"$lte", 20},
779				}},
780			})
781
782		// End Example 32
783
784		require.NoError(t, err)
785		requireCursorLength(t, cursor, 3)
786	}
787
788	{
789		// Start Example 33
790
791		cursor, err := coll.Find(
792			context.Background(),
793			bson.D{
794				{"instock.qty", bson.D{
795					{"$lte", 20},
796				}},
797			})
798
799		// End Example 33
800
801		require.NoError(t, err)
802		requireCursorLength(t, cursor, 5)
803	}
804
805	{
806		// Start Example 34
807
808		cursor, err := coll.Find(
809			context.Background(),
810			bson.D{
811				{"instock", bson.D{
812					{"$elemMatch", bson.D{
813						{"qty", 5},
814						{"warehouse", "A"},
815					}},
816				}},
817			})
818
819		// End Example 34
820
821		require.NoError(t, err)
822		requireCursorLength(t, cursor, 1)
823	}
824
825	{
826		// Start Example 35
827
828		cursor, err := coll.Find(
829			context.Background(),
830			bson.D{
831				{"instock", bson.D{
832					{"$elemMatch", bson.D{
833						{"qty", bson.D{
834							{"$gt", 10},
835							{"$lte", 20},
836						}},
837					}},
838				}},
839			})
840
841		// End Example 35
842
843		require.NoError(t, err)
844		requireCursorLength(t, cursor, 3)
845	}
846
847	{
848		// Start Example 36
849
850		cursor, err := coll.Find(
851			context.Background(),
852			bson.D{
853				{"instock.qty", bson.D{
854					{"$gt", 10},
855					{"$lte", 20},
856				}},
857			})
858
859		// End Example 36
860
861		require.NoError(t, err)
862		requireCursorLength(t, cursor, 4)
863	}
864
865	{
866		// Start Example 37
867
868		cursor, err := coll.Find(
869			context.Background(),
870			bson.D{
871				{"instock.qty", 5},
872				{"instock.warehouse", "A"},
873			})
874
875		// End Example 37
876
877		require.NoError(t, err)
878		requireCursorLength(t, cursor, 2)
879	}
880}
881
882// QueryNullMissingFieldsExamples contains examples for querying fields that are null or missing.
883func QueryNullMissingFieldsExamples(t *testing.T, db *mongo.Database) {
884	coll := db.Collection("inventory_query_null_missing")
885
886	err := coll.Drop(context.Background())
887	require.NoError(t, err)
888
889	{
890		// Start Example 38
891
892		docs := []interface{}{
893			bson.D{
894				{"_id", 1},
895				{"item", nil},
896			},
897			bson.D{
898				{"_id", 2},
899			},
900		}
901
902		result, err := coll.InsertMany(context.Background(), docs)
903
904		// End Example 38
905
906		require.NoError(t, err)
907		require.Len(t, result.InsertedIDs, 2)
908	}
909
910	{
911		// Start Example 39
912
913		cursor, err := coll.Find(
914			context.Background(),
915			bson.D{
916				{"item", nil},
917			})
918
919		// End Example 39
920
921		require.NoError(t, err)
922		requireCursorLength(t, cursor, 2)
923	}
924
925	{
926		// Start Example 40
927
928		cursor, err := coll.Find(
929			context.Background(),
930			bson.D{
931				{"item", bson.D{
932					{"$type", 10},
933				}},
934			})
935
936		// End Example 40
937
938		require.NoError(t, err)
939		requireCursorLength(t, cursor, 1)
940	}
941
942	{
943		// Start Example 41
944
945		cursor, err := coll.Find(
946			context.Background(),
947			bson.D{
948				{"item", bson.D{
949					{"$exists", false},
950				}},
951			})
952
953		// End Example 41
954
955		require.NoError(t, err)
956		requireCursorLength(t, cursor, 1)
957	}
958}
959
960// ProjectionExamples contains examples for specifying projections in find operations.
961func ProjectionExamples(t *testing.T, db *mongo.Database) {
962	coll := db.Collection("inventory_project")
963
964	err := coll.Drop(context.Background())
965	require.NoError(t, err)
966
967	{
968		// Start Example 42
969
970		docs := []interface{}{
971			bson.D{
972				{"item", "journal"},
973				{"status", "A"},
974				{"size", bson.D{
975					{"h", 14},
976					{"w", 21},
977					{"uom", "cm"},
978				}},
979				{"instock", bson.A{
980					bson.D{
981						{"warehouse", "A"},
982						{"qty", 5},
983					},
984				}},
985			},
986			bson.D{
987				{"item", "notebook"},
988				{"status", "A"},
989				{"size", bson.D{
990					{"h", 8.5},
991					{"w", 11},
992					{"uom", "in"},
993				}},
994				{"instock", bson.A{
995					bson.D{
996						{"warehouse", "EC"},
997						{"qty", 5},
998					},
999				}},
1000			},
1001			bson.D{
1002				{"item", "paper"},
1003				{"status", "D"},
1004				{"size", bson.D{
1005					{"h", 8.5},
1006					{"w", 11},
1007					{"uom", "in"},
1008				}},
1009				{"instock", bson.A{
1010					bson.D{
1011						{"warehouse", "A"},
1012						{"qty", 60},
1013					},
1014				}},
1015			},
1016			bson.D{
1017				{"item", "planner"},
1018				{"status", "D"},
1019				{"size", bson.D{
1020					{"h", 22.85},
1021					{"w", 30},
1022					{"uom", "cm"},
1023				}},
1024				{"instock", bson.A{
1025					bson.D{
1026						{"warehouse", "A"},
1027						{"qty", 40},
1028					},
1029				}},
1030			},
1031			bson.D{
1032				{"item", "postcard"},
1033				{"status", "A"},
1034				{"size", bson.D{
1035					{"h", 10},
1036					{"w", 15.25},
1037					{"uom", "cm"},
1038				}},
1039				{"instock", bson.A{
1040					bson.D{
1041						{"warehouse", "B"},
1042						{"qty", 15},
1043					},
1044					bson.D{
1045						{"warehouse", "EC"},
1046						{"qty", 35},
1047					},
1048				}},
1049			},
1050		}
1051
1052		result, err := coll.InsertMany(context.Background(), docs)
1053
1054		// End Example 42
1055
1056		require.NoError(t, err)
1057		require.Len(t, result.InsertedIDs, 5)
1058	}
1059
1060	{
1061		// Start Example 43
1062
1063		cursor, err := coll.Find(
1064			context.Background(),
1065			bson.D{{"status", "A"}},
1066		)
1067
1068		// End Example 43
1069
1070		require.NoError(t, err)
1071		requireCursorLength(t, cursor, 3)
1072	}
1073
1074	{
1075		// Start Example 44
1076
1077		projection := bson.D{
1078			{"item", 1},
1079			{"status", 1},
1080		}
1081
1082		cursor, err := coll.Find(
1083			context.Background(),
1084			bson.D{
1085				{"status", "A"},
1086			},
1087			options.Find().SetProjection(projection),
1088		)
1089
1090		// End Example 44
1091
1092		require.NoError(t, err)
1093
1094		for cursor.Next(context.Background()) {
1095			doc := cursor.Current
1096
1097			require.True(t, containsKey(doc, "_id"))
1098			require.True(t, containsKey(doc, "item"))
1099			require.True(t, containsKey(doc, "status"))
1100			require.False(t, containsKey(doc, "size"))
1101			require.False(t, containsKey(doc, "instock"))
1102		}
1103
1104		require.NoError(t, cursor.Err())
1105	}
1106
1107	{
1108		// Start Example 45
1109
1110		projection := bson.D{
1111			{"item", 1},
1112			{"status", 1},
1113			{"_id", 0},
1114		}
1115
1116		cursor, err := coll.Find(
1117			context.Background(),
1118			bson.D{
1119				{"status", "A"},
1120			},
1121			options.Find().SetProjection(projection),
1122		)
1123
1124		// End Example 45
1125
1126		require.NoError(t, err)
1127
1128		for cursor.Next(context.Background()) {
1129			doc := cursor.Current
1130
1131			require.False(t, containsKey(doc, "_id"))
1132			require.True(t, containsKey(doc, "item"))
1133			require.True(t, containsKey(doc, "status"))
1134			require.False(t, containsKey(doc, "size"))
1135			require.False(t, containsKey(doc, "instock"))
1136		}
1137
1138		require.NoError(t, cursor.Err())
1139	}
1140
1141	{
1142		// Start Example 46
1143
1144		projection := bson.D{
1145			{"status", 0},
1146			{"instock", 0},
1147		}
1148
1149		cursor, err := coll.Find(
1150			context.Background(),
1151			bson.D{
1152				{"status", "A"},
1153			},
1154			options.Find().SetProjection(projection),
1155		)
1156
1157		// End Example 46
1158
1159		require.NoError(t, err)
1160
1161		for cursor.Next(context.Background()) {
1162			doc := cursor.Current
1163
1164			require.True(t, containsKey(doc, "_id"))
1165			require.True(t, containsKey(doc, "item"))
1166			require.False(t, containsKey(doc, "status"))
1167			require.True(t, containsKey(doc, "size"))
1168			require.False(t, containsKey(doc, "instock"))
1169		}
1170
1171		require.NoError(t, cursor.Err())
1172	}
1173
1174	{
1175		// Start Example 47
1176
1177		projection := bson.D{
1178			{"item", 1},
1179			{"status", 1},
1180			{"size.uom", 1},
1181		}
1182
1183		cursor, err := coll.Find(
1184			context.Background(),
1185			bson.D{
1186				{"status", "A"},
1187			},
1188			options.Find().SetProjection(projection),
1189		)
1190
1191		// End Example 47
1192
1193		require.NoError(t, err)
1194
1195		for cursor.Next(context.Background()) {
1196			doc := cursor.Current
1197
1198			require.True(t, containsKey(doc, "_id"))
1199			require.True(t, containsKey(doc, "item"))
1200			require.True(t, containsKey(doc, "status"))
1201			require.True(t, containsKey(doc, "size"))
1202			require.False(t, containsKey(doc, "instock"))
1203
1204			require.True(t, containsKey(doc, "size", "uom"))
1205			require.False(t, containsKey(doc, "size", "h"))
1206			require.False(t, containsKey(doc, "size", "w"))
1207
1208		}
1209
1210		require.NoError(t, cursor.Err())
1211	}
1212
1213	{
1214		// Start Example 48
1215
1216		projection := bson.D{
1217			{"size.uom", 0},
1218		}
1219
1220		cursor, err := coll.Find(
1221			context.Background(),
1222			bson.D{
1223				{"status", "A"},
1224			},
1225			options.Find().SetProjection(projection),
1226		)
1227
1228		// End Example 48
1229
1230		require.NoError(t, err)
1231
1232		for cursor.Next(context.Background()) {
1233			doc := cursor.Current
1234
1235			require.True(t, containsKey(doc, "_id"))
1236			require.True(t, containsKey(doc, "item"))
1237			require.True(t, containsKey(doc, "status"))
1238			require.True(t, containsKey(doc, "size"))
1239			require.True(t, containsKey(doc, "instock"))
1240
1241			require.False(t, containsKey(doc, "size", "uom"))
1242			require.True(t, containsKey(doc, "size", "h"))
1243			require.True(t, containsKey(doc, "size", "w"))
1244
1245		}
1246
1247		require.NoError(t, cursor.Err())
1248	}
1249
1250	{
1251		// Start Example 49
1252
1253		projection := bson.D{
1254			{"item", 1},
1255			{"status", 1},
1256			{"instock.qty", 1},
1257		}
1258
1259		cursor, err := coll.Find(
1260			context.Background(),
1261			bson.D{
1262				{"status", "A"},
1263			},
1264			options.Find().SetProjection(projection),
1265		)
1266
1267		// End Example 49
1268
1269		require.NoError(t, err)
1270
1271		for cursor.Next(context.Background()) {
1272			doc := cursor.Current
1273
1274			require.True(t, containsKey(doc, "_id"))
1275			require.True(t, containsKey(doc, "item"))
1276			require.True(t, containsKey(doc, "status"))
1277			require.False(t, containsKey(doc, "size"))
1278			require.True(t, containsKey(doc, "instock"))
1279
1280			instock, err := doc.LookupErr("instock")
1281			require.NoError(t, err)
1282
1283			vals, err := instock.Array().Values()
1284			require.NoError(t, err)
1285
1286			for _, val := range vals {
1287				require.Equal(t, bson.TypeEmbeddedDocument, val.Type)
1288				subdoc := val.Document()
1289				elems, err := subdoc.Elements()
1290				require.NoError(t, err)
1291
1292				require.Equal(t, 1, len(elems))
1293				_, err = subdoc.LookupErr("qty")
1294				require.NoError(t, err)
1295			}
1296		}
1297
1298		require.NoError(t, cursor.Err())
1299	}
1300
1301	{
1302		// Start Example 50
1303
1304		projection := bson.D{
1305			{"item", 1},
1306			{"status", 1},
1307			{"instock", bson.D{
1308				{"$slice", -1},
1309			}},
1310		}
1311
1312		cursor, err := coll.Find(
1313			context.Background(),
1314			bson.D{
1315				{"status", "A"},
1316			},
1317			options.Find().SetProjection(projection),
1318		)
1319
1320		// End Example 50
1321
1322		require.NoError(t, err)
1323
1324		for cursor.Next(context.Background()) {
1325			doc := cursor.Current
1326
1327			require.True(t, containsKey(doc, "_id"))
1328			require.True(t, containsKey(doc, "item"))
1329			require.True(t, containsKey(doc, "status"))
1330			require.False(t, containsKey(doc, "size"))
1331			require.True(t, containsKey(doc, "instock"))
1332
1333			instock, err := doc.LookupErr("instock")
1334			require.NoError(t, err)
1335			vals, err := instock.Array().Values()
1336			require.NoError(t, err)
1337			require.Equal(t, len(vals), 1)
1338		}
1339
1340		require.NoError(t, cursor.Err())
1341	}
1342}
1343
1344// UpdateExamples contains examples of update operations.
1345func UpdateExamples(t *testing.T, db *mongo.Database) {
1346	coll := db.Collection("inventory_update")
1347
1348	err := coll.Drop(context.Background())
1349	require.NoError(t, err)
1350
1351	{
1352		// Start Example 51
1353
1354		docs := []interface{}{
1355			bson.D{
1356				{"item", "canvas"},
1357				{"qty", 100},
1358				{"size", bson.D{
1359					{"h", 28},
1360					{"w", 35.5},
1361					{"uom", "cm"},
1362				}},
1363				{"status", "A"},
1364			},
1365			bson.D{
1366				{"item", "journal"},
1367				{"qty", 25},
1368				{"size", bson.D{
1369					{"h", 14},
1370					{"w", 21},
1371					{"uom", "cm"},
1372				}},
1373				{"status", "A"},
1374			},
1375			bson.D{
1376				{"item", "mat"},
1377				{"qty", 85},
1378				{"size", bson.D{
1379					{"h", 27.9},
1380					{"w", 35.5},
1381					{"uom", "cm"},
1382				}},
1383				{"status", "A"},
1384			},
1385			bson.D{
1386				{"item", "mousepad"},
1387				{"qty", 25},
1388				{"size", bson.D{
1389					{"h", 19},
1390					{"w", 22.85},
1391					{"uom", "in"},
1392				}},
1393				{"status", "P"},
1394			},
1395			bson.D{
1396				{"item", "notebook"},
1397				{"qty", 50},
1398				{"size", bson.D{
1399					{"h", 8.5},
1400					{"w", 11},
1401					{"uom", "in"},
1402				}},
1403				{"status", "P"},
1404			},
1405			bson.D{
1406				{"item", "paper"},
1407				{"qty", 100},
1408				{"size", bson.D{
1409					{"h", 8.5},
1410					{"w", 11},
1411					{"uom", "in"},
1412				}},
1413				{"status", "D"},
1414			},
1415			bson.D{
1416				{"item", "planner"},
1417				{"qty", 75},
1418				{"size", bson.D{
1419					{"h", 22.85},
1420					{"w", 30},
1421					{"uom", "cm"},
1422				}},
1423				{"status", "D"},
1424			},
1425			bson.D{
1426				{"item", "postcard"},
1427				{"qty", 45},
1428				{"size", bson.D{
1429					{"h", 10},
1430					{"w", 15.25},
1431					{"uom", "cm"},
1432				}},
1433				{"status", "A"},
1434			},
1435			bson.D{
1436				{"item", "sketchbook"},
1437				{"qty", 80},
1438				{"size", bson.D{
1439					{"h", 14},
1440					{"w", 21},
1441					{"uom", "cm"},
1442				}},
1443				{"status", "A"},
1444			},
1445			bson.D{
1446				{"item", "sketch pad"},
1447				{"qty", 95},
1448				{"size", bson.D{
1449					{"h", 22.85},
1450					{"w", 30.5},
1451					{"uom", "cm"},
1452				}},
1453				{"status", "A"},
1454			},
1455		}
1456
1457		result, err := coll.InsertMany(context.Background(), docs)
1458
1459		// End Example 51
1460
1461		require.NoError(t, err)
1462		require.Len(t, result.InsertedIDs, 10)
1463	}
1464
1465	{
1466		// Start Example 52
1467
1468		result, err := coll.UpdateOne(
1469			context.Background(),
1470			bson.D{
1471				{"item", "paper"},
1472			},
1473			bson.D{
1474				{"$set", bson.D{
1475					{"size.uom", "cm"},
1476					{"status", "P"},
1477				}},
1478				{"$currentDate", bson.D{
1479					{"lastModified", true},
1480				}},
1481			},
1482		)
1483
1484		// End Example 52
1485
1486		require.NoError(t, err)
1487		require.Equal(t, int64(1), result.MatchedCount)
1488		require.Equal(t, int64(1), result.ModifiedCount)
1489
1490		cursor, err := coll.Find(
1491			context.Background(),
1492			bson.D{
1493				{"item", "paper"},
1494			})
1495
1496		require.NoError(t, err)
1497
1498		for cursor.Next(context.Background()) {
1499			doc := cursor.Current
1500
1501			uom, err := doc.LookupErr("size", "uom")
1502			require.NoError(t, err)
1503			require.Equal(t, uom.StringValue(), "cm")
1504
1505			status, err := doc.LookupErr("status")
1506			require.NoError(t, err)
1507			require.Equal(t, status.StringValue(), "P")
1508
1509			require.True(t, containsKey(doc, "lastModified"))
1510		}
1511
1512		require.NoError(t, cursor.Err())
1513	}
1514
1515	{
1516		// Start Example 53
1517
1518		result, err := coll.UpdateMany(
1519			context.Background(),
1520			bson.D{
1521				{"qty", bson.D{
1522					{"$lt", 50},
1523				}},
1524			},
1525			bson.D{
1526				{"$set", bson.D{
1527					{"size.uom", "cm"},
1528					{"status", "P"},
1529				}},
1530				{"$currentDate", bson.D{
1531					{"lastModified", true},
1532				}},
1533			},
1534		)
1535
1536		// End Example 53
1537
1538		require.NoError(t, err)
1539		require.Equal(t, int64(3), result.MatchedCount)
1540		require.Equal(t, int64(3), result.ModifiedCount)
1541
1542		cursor, err := coll.Find(
1543			context.Background(),
1544			bson.D{
1545				{"qty", bson.D{
1546					{"$lt", 50},
1547				}},
1548			})
1549
1550		require.NoError(t, err)
1551
1552		for cursor.Next(context.Background()) {
1553			doc := cursor.Current
1554
1555			uom, err := doc.LookupErr("size", "uom")
1556			require.NoError(t, err)
1557			require.Equal(t, uom.StringValue(), "cm")
1558
1559			status, err := doc.LookupErr("status")
1560			require.NoError(t, err)
1561			require.Equal(t, status.StringValue(), "P")
1562
1563			require.True(t, containsKey(doc, "lastModified"))
1564		}
1565
1566		require.NoError(t, cursor.Err())
1567	}
1568
1569	{
1570		// Start Example 54
1571
1572		result, err := coll.ReplaceOne(
1573			context.Background(),
1574			bson.D{
1575				{"item", "paper"},
1576			},
1577			bson.D{
1578				{"item", "paper"},
1579				{"instock", bson.A{
1580					bson.D{
1581						{"warehouse", "A"},
1582						{"qty", 60},
1583					},
1584					bson.D{
1585						{"warehouse", "B"},
1586						{"qty", 40},
1587					},
1588				}},
1589			},
1590		)
1591
1592		// End Example 54
1593
1594		require.NoError(t, err)
1595		require.Equal(t, int64(1), result.MatchedCount)
1596		require.Equal(t, int64(1), result.ModifiedCount)
1597
1598		cursor, err := coll.Find(
1599			context.Background(),
1600			bson.D{
1601				{"item", "paper"},
1602			})
1603
1604		require.NoError(t, err)
1605
1606		for cursor.Next(context.Background()) {
1607			require.True(t, containsKey(cursor.Current, "_id"))
1608			require.True(t, containsKey(cursor.Current, "item"))
1609			require.True(t, containsKey(cursor.Current, "instock"))
1610
1611			instock, err := cursor.Current.LookupErr("instock")
1612			require.NoError(t, err)
1613			vals, err := instock.Array().Values()
1614			require.NoError(t, err)
1615			require.Equal(t, len(vals), 2)
1616
1617		}
1618
1619		require.NoError(t, cursor.Err())
1620	}
1621
1622}
1623
1624// DeleteExamples contains examples of delete operations.
1625func DeleteExamples(t *testing.T, db *mongo.Database) {
1626	coll := db.Collection("inventory_delete")
1627
1628	err := coll.Drop(context.Background())
1629	require.NoError(t, err)
1630
1631	{
1632		// Start Example 55
1633		docs := []interface{}{
1634			bson.D{
1635				{"item", "journal"},
1636				{"qty", 25},
1637				{"size", bson.D{
1638					{"h", 14},
1639					{"w", 21},
1640					{"uom", "cm"},
1641				}},
1642				{"status", "A"},
1643			},
1644			bson.D{
1645				{"item", "notebook"},
1646				{"qty", 50},
1647				{"size", bson.D{
1648					{"h", 8.5},
1649					{"w", 11},
1650					{"uom", "in"},
1651				}},
1652				{"status", "P"},
1653			},
1654			bson.D{
1655				{"item", "paper"},
1656				{"qty", 100},
1657				{"size", bson.D{
1658					{"h", 8.5},
1659					{"w", 11},
1660					{"uom", "in"},
1661				}},
1662				{"status", "D"},
1663			},
1664			bson.D{
1665				{"item", "planner"},
1666				{"qty", 75},
1667				{"size", bson.D{
1668					{"h", 22.85},
1669					{"w", 30},
1670					{"uom", "cm"},
1671				}},
1672				{"status", "D"},
1673			},
1674			bson.D{
1675				{"item", "postcard"},
1676				{"qty", 45},
1677				{"size", bson.D{
1678					{"h", 10},
1679					{"w", 15.25},
1680					{"uom", "cm"},
1681				}},
1682				{"status", "A"},
1683			},
1684		}
1685
1686		result, err := coll.InsertMany(context.Background(), docs)
1687
1688		// End Example 55
1689
1690		require.NoError(t, err)
1691		require.Len(t, result.InsertedIDs, 5)
1692	}
1693
1694	{
1695		// Start Example 57
1696
1697		result, err := coll.DeleteMany(
1698			context.Background(),
1699			bson.D{
1700				{"status", "A"},
1701			},
1702		)
1703
1704		// End Example 57
1705
1706		require.NoError(t, err)
1707		require.Equal(t, int64(2), result.DeletedCount)
1708	}
1709
1710	{
1711		// Start Example 58
1712
1713		result, err := coll.DeleteOne(
1714			context.Background(),
1715			bson.D{
1716				{"status", "D"},
1717			},
1718		)
1719
1720		// End Example 58
1721
1722		require.NoError(t, err)
1723		require.Equal(t, int64(1), result.DeletedCount)
1724
1725	}
1726
1727	{
1728		// Start Example 56
1729
1730		result, err := coll.DeleteMany(context.Background(), bson.D{})
1731
1732		// End Example 56
1733
1734		require.NoError(t, err)
1735		require.Equal(t, int64(2), result.DeletedCount)
1736	}
1737}
1738
1739var log = logger.New(ioutil.Discard, "", logger.LstdFlags)
1740
1741// Start Transactions Intro Example 1
1742
1743// UpdateEmployeeInfo is an example function demonstrating transactions.
1744func UpdateEmployeeInfo(ctx context.Context, client *mongo.Client) error {
1745	employees := client.Database("hr").Collection("employees")
1746	events := client.Database("reporting").Collection("events")
1747
1748	return client.UseSession(ctx, func(sctx mongo.SessionContext) error {
1749		err := sctx.StartTransaction(options.Transaction().
1750			SetReadConcern(readconcern.Snapshot()).
1751			SetWriteConcern(writeconcern.New(writeconcern.WMajority())),
1752		)
1753		if err != nil {
1754			return err
1755		}
1756
1757		_, err = employees.UpdateOne(sctx, bson.D{{"employee", 3}}, bson.D{{"$set", bson.D{{"status", "Inactive"}}}})
1758		if err != nil {
1759			sctx.AbortTransaction(sctx)
1760			log.Println("caught exception during transaction, aborting.")
1761			return err
1762		}
1763		_, err = events.InsertOne(sctx, bson.D{{"employee", 3}, {"status", bson.D{{"new", "Inactive"}, {"old", "Active"}}}})
1764		if err != nil {
1765			sctx.AbortTransaction(sctx)
1766			log.Println("caught exception during transaction, aborting.")
1767			return err
1768		}
1769
1770		for {
1771			err = sctx.CommitTransaction(sctx)
1772			switch e := err.(type) {
1773			case nil:
1774				return nil
1775			case mongo.CommandError:
1776				if e.HasErrorLabel("UnknownTransactionCommitResult") {
1777					log.Println("UnknownTransactionCommitResult, retrying commit operation...")
1778					continue
1779				}
1780				log.Println("Error during commit...")
1781				return e
1782			default:
1783				log.Println("Error during commit...")
1784				return e
1785			}
1786		}
1787	})
1788}
1789
1790// End Transactions Intro Example 1
1791
1792// Start Transactions Retry Example 1
1793
1794// RunTransactionWithRetry is an example function demonstrating transaction retry logic.
1795func RunTransactionWithRetry(sctx mongo.SessionContext, txnFn func(mongo.SessionContext) error) error {
1796	for {
1797		err := txnFn(sctx) // Performs transaction.
1798		if err == nil {
1799			return nil
1800		}
1801
1802		log.Println("Transaction aborted. Caught exception during transaction.")
1803
1804		// If transient error, retry the whole transaction
1805		if cmdErr, ok := err.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") {
1806			log.Println("TransientTransactionError, retrying transaction...")
1807			continue
1808		}
1809		return err
1810	}
1811}
1812
1813// End Transactions Retry Example 1
1814
1815// Start Transactions Retry Example 2
1816
1817// CommitWithRetry is an example function demonstrating transaction commit with retry logic.
1818func CommitWithRetry(sctx mongo.SessionContext) error {
1819	for {
1820		err := sctx.CommitTransaction(sctx)
1821		switch e := err.(type) {
1822		case nil:
1823			log.Println("Transaction committed.")
1824			return nil
1825		case mongo.CommandError:
1826			// Can retry commit
1827			if e.HasErrorLabel("UnknownTransactionCommitResult") {
1828				log.Println("UnknownTransactionCommitResult, retrying commit operation...")
1829				continue
1830			}
1831			log.Println("Error during commit...")
1832			return e
1833		default:
1834			log.Println("Error during commit...")
1835			return e
1836		}
1837	}
1838}
1839
1840// End Transactions Retry Example 2
1841
1842// TransactionsExamples contains examples for transaction operations.
1843func TransactionsExamples(ctx context.Context, client *mongo.Client) error {
1844	_, err := client.Database("hr").Collection("employees").InsertOne(ctx, bson.D{{"pi", 3.14159}})
1845	if err != nil {
1846		return err
1847	}
1848	_, err = client.Database("hr").Collection("employees").DeleteOne(ctx, bson.D{{"pi", 3.14159}})
1849	if err != nil {
1850		return err
1851	}
1852	_, err = client.Database("reporting").Collection("events").InsertOne(ctx, bson.D{{"pi", 3.14159}})
1853	if err != nil {
1854		return err
1855	}
1856	_, err = client.Database("reporting").Collection("events").DeleteOne(ctx, bson.D{{"pi", 3.14159}})
1857	if err != nil {
1858		return err
1859	}
1860	// Start Transactions Retry Example 3
1861
1862	runTransactionWithRetry := func(sctx mongo.SessionContext, txnFn func(mongo.SessionContext) error) error {
1863		for {
1864			err := txnFn(sctx) // Performs transaction.
1865			if err == nil {
1866				return nil
1867			}
1868
1869			log.Println("Transaction aborted. Caught exception during transaction.")
1870
1871			// If transient error, retry the whole transaction
1872			if cmdErr, ok := err.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") {
1873				log.Println("TransientTransactionError, retrying transaction...")
1874				continue
1875			}
1876			return err
1877		}
1878	}
1879
1880	commitWithRetry := func(sctx mongo.SessionContext) error {
1881		for {
1882			err := sctx.CommitTransaction(sctx)
1883			switch e := err.(type) {
1884			case nil:
1885				log.Println("Transaction committed.")
1886				return nil
1887			case mongo.CommandError:
1888				// Can retry commit
1889				if e.HasErrorLabel("UnknownTransactionCommitResult") {
1890					log.Println("UnknownTransactionCommitResult, retrying commit operation...")
1891					continue
1892				}
1893				log.Println("Error during commit...")
1894				return e
1895			default:
1896				log.Println("Error during commit...")
1897				return e
1898			}
1899		}
1900	}
1901
1902	// Updates two collections in a transaction.
1903	updateEmployeeInfo := func(sctx mongo.SessionContext) error {
1904		employees := client.Database("hr").Collection("employees")
1905		events := client.Database("reporting").Collection("events")
1906
1907		err := sctx.StartTransaction(options.Transaction().
1908			SetReadConcern(readconcern.Snapshot()).
1909			SetWriteConcern(writeconcern.New(writeconcern.WMajority())),
1910		)
1911		if err != nil {
1912			return err
1913		}
1914
1915		_, err = employees.UpdateOne(sctx, bson.D{{"employee", 3}}, bson.D{{"$set", bson.D{{"status", "Inactive"}}}})
1916		if err != nil {
1917			sctx.AbortTransaction(sctx)
1918			log.Println("caught exception during transaction, aborting.")
1919			return err
1920		}
1921		_, err = events.InsertOne(sctx, bson.D{{"employee", 3}, {"status", bson.D{{"new", "Inactive"}, {"old", "Active"}}}})
1922		if err != nil {
1923			sctx.AbortTransaction(sctx)
1924			log.Println("caught exception during transaction, aborting.")
1925			return err
1926		}
1927
1928		return commitWithRetry(sctx)
1929	}
1930
1931	return client.UseSessionWithOptions(
1932		ctx, options.Session().SetDefaultReadPreference(readpref.Primary()),
1933		func(sctx mongo.SessionContext) error {
1934			return runTransactionWithRetry(sctx, updateEmployeeInfo)
1935		},
1936	)
1937}
1938
1939// End Transactions Retry Example 3
1940
1941// Start Transactions withTxn API Example 1
1942
1943// WithTransactionExample is an example of using the Session.WithTransaction function.
1944func WithTransactionExample() {
1945	ctx := context.Background()
1946	// For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
1947	// uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl"
1948	// For a sharded cluster, connect to the mongos instances; e.g.
1949	// uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/"
1950	var uri string
1951
1952	clientOpts := options.Client().ApplyURI(uri)
1953	client, err := mongo.Connect(ctx, clientOpts)
1954	if err != nil {
1955		panic(err)
1956	}
1957	defer func() { _ = client.Disconnect(ctx) }()
1958
1959	// Prereq: Create collections.
1960	wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second))
1961	wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority)
1962	fooColl := client.Database("mydb1").Collection("foo", wcMajorityCollectionOpts)
1963	barColl := client.Database("mydb1").Collection("bar", wcMajorityCollectionOpts)
1964
1965	// Step 1: Define the callback that specifies the sequence of operations to perform inside the transaction.
1966	callback := func(sessCtx mongo.SessionContext) (interface{}, error) {
1967		// Important: You must pass sessCtx as the Context parameter to the operations for them to be executed in the
1968		// transaction.
1969		if _, err := fooColl.InsertOne(sessCtx, bson.D{{"abc", 1}}); err != nil {
1970			return nil, err
1971		}
1972		if _, err := barColl.InsertOne(sessCtx, bson.D{{"xyz", 999}}); err != nil {
1973			return nil, err
1974		}
1975
1976		return nil, nil
1977	}
1978
1979	// Step 2: Start a session and run the callback using WithTransaction.
1980	session, err := client.StartSession()
1981	if err != nil {
1982		panic(err)
1983	}
1984	defer session.EndSession(ctx)
1985
1986	result, err := session.WithTransaction(ctx, callback)
1987	if err != nil {
1988		panic(err)
1989	}
1990	fmt.Printf("result: %v\n", result)
1991}
1992
1993// End Transactions withTxn API Example 1
1994
1995// ChangeStreamExamples contains examples of changestream operations.
1996func ChangeStreamExamples(t *testing.T, db *mongo.Database) {
1997	ctx := context.Background()
1998
1999	coll := db.Collection("inventory_changestream")
2000
2001	err := coll.Drop(context.Background())
2002	require.NoError(t, err)
2003
2004	_, err = coll.InsertOne(ctx, bson.D{{"x", int32(1)}})
2005	require.NoError(t, err)
2006
2007	var stop int32
2008
2009	doInserts := func(coll *mongo.Collection) {
2010		for atomic.LoadInt32(&stop) == 0 {
2011			_, err = coll.InsertOne(ctx, bson.D{{"x", 1}})
2012			time.Sleep(10 * time.Millisecond)
2013			coll.DeleteOne(ctx, bson.D{{"x", 1}})
2014		}
2015	}
2016
2017	go doInserts(coll)
2018
2019	{
2020		// Start Changestream Example 1
2021
2022		cs, err := coll.Watch(ctx, mongo.Pipeline{})
2023		require.NoError(t, err)
2024		defer cs.Close(ctx)
2025
2026		ok := cs.Next(ctx)
2027		next := cs.Current
2028
2029		// End Changestream Example 1
2030
2031		require.True(t, ok)
2032		require.NoError(t, err)
2033		require.NotEqual(t, len(next), 0)
2034	}
2035	{
2036		// Start Changestream Example 2
2037
2038		cs, err := coll.Watch(ctx, mongo.Pipeline{}, options.ChangeStream().SetFullDocument(options.UpdateLookup))
2039		require.NoError(t, err)
2040		defer cs.Close(ctx)
2041
2042		ok := cs.Next(ctx)
2043		next := cs.Current
2044
2045		// End Changestream Example 2
2046
2047		require.True(t, ok)
2048		require.NoError(t, err)
2049		require.NotEqual(t, len(next), 0)
2050	}
2051
2052	{
2053		original, err := coll.Watch(ctx, mongo.Pipeline{})
2054		require.NoError(t, err)
2055		defer original.Close(ctx)
2056
2057		ok := original.Next(ctx)
2058		require.True(t, ok)
2059
2060		// Start Changestream Example 3
2061		resumeToken := original.ResumeToken()
2062
2063		cs, err := coll.Watch(ctx, mongo.Pipeline{}, options.ChangeStream().SetResumeAfter(resumeToken))
2064		require.NoError(t, err)
2065		defer cs.Close(ctx)
2066
2067		ok = cs.Next(ctx)
2068		result := cs.Current
2069
2070		// End Changestream Example 3
2071
2072		require.True(t, ok)
2073		require.NoError(t, err)
2074		require.NotEqual(t, len(result), 0)
2075	}
2076
2077	{
2078		// Start Changestream Example 4
2079		pipeline := mongo.Pipeline{bson.D{{"$match", bson.D{{"$or",
2080			bson.A{
2081				bson.D{{"fullDocument.username", "alice"}},
2082				bson.D{{"operationType", "delete"}}}}},
2083		}}}
2084		cs, err := coll.Watch(ctx, pipeline)
2085		require.NoError(t, err)
2086		defer cs.Close(ctx)
2087
2088		ok := cs.Next(ctx)
2089		next := cs.Current
2090
2091		// End Changestream Example 4
2092
2093		require.True(t, ok)
2094		require.NoError(t, err)
2095		require.NotEqual(t, len(next), 0)
2096	}
2097
2098	atomic.StoreInt32(&stop, 1)
2099}
2100