...

Source file src/go.mongodb.org/mongo-driver/examples/documentation_examples/examples.go

Documentation: go.mongodb.org/mongo-driver/examples/documentation_examples

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

View as plain text