// Copyright (C) MongoDB, Inc. 2017-present. // // Licensed under the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 // NOTE: Any time this file is modified, a WEBSITE ticket should be opened to sync the changes with // the "What is MongoDB" webpage, which the example was originally added to as part of WEBSITE-5148. package documentation_examples import ( "context" "fmt" "io/ioutil" logger "log" "strings" "sync/atomic" "testing" "time" "github.com/stretchr/testify/require" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readconcern" "go.mongodb.org/mongo-driver/mongo/readpref" "go.mongodb.org/mongo-driver/mongo/writeconcern" ) func requireCursorLength(t *testing.T, cursor *mongo.Cursor, length int) { i := 0 for cursor.Next(context.Background()) { i++ } require.NoError(t, cursor.Err()) require.Equal(t, i, length) } func containsKey(doc bson.Raw, key ...string) bool { _, err := doc.LookupErr(key...) if err != nil { return false } return true } func parseDate(t *testing.T, dateString string) time.Time { rfc3339MilliLayout := "2006-01-02T15:04:05.999Z07:00" // layout defined with Go reference time parsedDate, err := time.Parse(rfc3339MilliLayout, dateString) require.NoError(t, err) return parsedDate } // InsertExamples contains examples for insert operations. func InsertExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_insert") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 1 result, err := coll.InsertOne( context.Background(), bson.D{ {"item", "canvas"}, {"qty", 100}, {"tags", bson.A{"cotton"}}, {"size", bson.D{ {"h", 28}, {"w", 35.5}, {"uom", "cm"}, }}, }) // End Example 1 require.NoError(t, err) require.NotNil(t, result.InsertedID) } { // Start Example 2 cursor, err := coll.Find( context.Background(), bson.D{{"item", "canvas"}}, ) // End Example 2 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 3 result, err := coll.InsertMany( context.Background(), []interface{}{ bson.D{ {"item", "journal"}, {"qty", int32(25)}, {"tags", bson.A{"blank", "red"}}, {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, }, bson.D{ {"item", "mat"}, {"qty", int32(25)}, {"tags", bson.A{"gray"}}, {"size", bson.D{ {"h", 27.9}, {"w", 35.5}, {"uom", "cm"}, }}, }, bson.D{ {"item", "mousepad"}, {"qty", 25}, {"tags", bson.A{"gel", "blue"}}, {"size", bson.D{ {"h", 19}, {"w", 22.85}, {"uom", "cm"}, }}, }, }) // End Example 3 require.NoError(t, err) require.Len(t, result.InsertedIDs, 3) } } // QueryToplevelFieldsExamples contains examples for querying top-level fields. func QueryToplevelFieldsExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_query_top") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 6 docs := []interface{}{ bson.D{ {"item", "journal"}, {"qty", 25}, {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "notebook"}, {"qty", 50}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "A"}, }, bson.D{ {"item", "paper"}, {"qty", 100}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "D"}, }, bson.D{ {"item", "planner"}, {"qty", 75}, {"size", bson.D{ {"h", 22.85}, {"w", 30}, {"uom", "cm"}, }}, {"status", "D"}, }, bson.D{ {"item", "postcard"}, {"qty", 45}, {"size", bson.D{ {"h", 10}, {"w", 15.25}, {"uom", "cm"}, }}, {"status", "A"}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 6 require.NoError(t, err) require.Len(t, result.InsertedIDs, 5) } { // Start Example 7 cursor, err := coll.Find( context.Background(), bson.D{}, ) // End Example 7 require.NoError(t, err) requireCursorLength(t, cursor, 5) } { // Start Example 9 cursor, err := coll.Find( context.Background(), bson.D{{"status", "D"}}, ) // End Example 9 require.NoError(t, err) requireCursorLength(t, cursor, 2) } { // Start Example 10 cursor, err := coll.Find( context.Background(), bson.D{{"status", bson.D{{"$in", bson.A{"A", "D"}}}}}) // End Example 10 require.NoError(t, err) requireCursorLength(t, cursor, 5) } { // Start Example 11 cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, {"qty", bson.D{{"$lt", 30}}}, }) // End Example 11 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 12 cursor, err := coll.Find( context.Background(), bson.D{ {"$or", bson.A{ bson.D{{"status", "A"}}, bson.D{{"qty", bson.D{{"$lt", 30}}}}, }}, }) // End Example 12 require.NoError(t, err) requireCursorLength(t, cursor, 3) } { // Start Example 13 cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, {"$or", bson.A{ bson.D{{"qty", bson.D{{"$lt", 30}}}}, bson.D{{"item", primitive.Regex{Pattern: "^p", Options: ""}}}, }}, }) // End Example 13 require.NoError(t, err) requireCursorLength(t, cursor, 2) } } // QueryEmbeddedDocumentsExamples contains examples for querying embedded document fields. func QueryEmbeddedDocumentsExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_query_embedded") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 14 docs := []interface{}{ bson.D{ {"item", "journal"}, {"qty", 25}, {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "notebook"}, {"qty", 50}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "A"}, }, bson.D{ {"item", "paper"}, {"qty", 100}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "D"}, }, bson.D{ {"item", "planner"}, {"qty", 75}, {"size", bson.D{ {"h", 22.85}, {"w", 30}, {"uom", "cm"}, }}, {"status", "D"}, }, bson.D{ {"item", "postcard"}, {"qty", 45}, {"size", bson.D{ {"h", 10}, {"w", 15.25}, {"uom", "cm"}, }}, {"status", "A"}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 14 require.NoError(t, err) require.Len(t, result.InsertedIDs, 5) } { // Start Example 15 cursor, err := coll.Find( context.Background(), bson.D{ {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, }) // End Example 15 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 16 cursor, err := coll.Find( context.Background(), bson.D{ {"size", bson.D{ {"w", 21}, {"h", 14}, {"uom", "cm"}, }}, }) // End Example 16 require.NoError(t, err) requireCursorLength(t, cursor, 0) } { // Start Example 17 cursor, err := coll.Find( context.Background(), bson.D{{"size.uom", "in"}}, ) // End Example 17 require.NoError(t, err) requireCursorLength(t, cursor, 2) } { // Start Example 18 cursor, err := coll.Find( context.Background(), bson.D{ {"size.h", bson.D{ {"$lt", 15}, }}, }) // End Example 18 require.NoError(t, err) requireCursorLength(t, cursor, 4) } { // Start Example 19 cursor, err := coll.Find( context.Background(), bson.D{ {"size.h", bson.D{ {"$lt", 15}, }}, {"size.uom", "in"}, {"status", "D"}, }) // End Example 19 require.NoError(t, err) requireCursorLength(t, cursor, 1) } } // QueryArraysExamples contains examples for querying array fields. func QueryArraysExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_query_array") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 20 docs := []interface{}{ bson.D{ {"item", "journal"}, {"qty", 25}, {"tags", bson.A{"blank", "red"}}, {"dim_cm", bson.A{14, 21}}, }, bson.D{ {"item", "notebook"}, {"qty", 50}, {"tags", bson.A{"red", "blank"}}, {"dim_cm", bson.A{14, 21}}, }, bson.D{ {"item", "paper"}, {"qty", 100}, {"tags", bson.A{"red", "blank", "plain"}}, {"dim_cm", bson.A{14, 21}}, }, bson.D{ {"item", "planner"}, {"qty", 75}, {"tags", bson.A{"blank", "red"}}, {"dim_cm", bson.A{22.85, 30}}, }, bson.D{ {"item", "postcard"}, {"qty", 45}, {"tags", bson.A{"blue"}}, {"dim_cm", bson.A{10, 15.25}}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 20 require.NoError(t, err) require.Len(t, result.InsertedIDs, 5) } { // Start Example 21 cursor, err := coll.Find( context.Background(), bson.D{{"tags", bson.A{"red", "blank"}}}, ) // End Example 21 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 22 cursor, err := coll.Find( context.Background(), bson.D{ {"tags", bson.D{{"$all", bson.A{"red", "blank"}}}}, }) // End Example 22 require.NoError(t, err) requireCursorLength(t, cursor, 4) } { // Start Example 23 cursor, err := coll.Find( context.Background(), bson.D{ {"tags", "red"}, }) // End Example 23 require.NoError(t, err) requireCursorLength(t, cursor, 4) } { // Start Example 24 cursor, err := coll.Find( context.Background(), bson.D{ {"dim_cm", bson.D{ {"$gt", 25}, }}, }) // End Example 24 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 25 cursor, err := coll.Find( context.Background(), bson.D{ {"dim_cm", bson.D{ {"$gt", 15}, {"$lt", 20}, }}, }) // End Example 25 require.NoError(t, err) requireCursorLength(t, cursor, 4) } { // Start Example 26 cursor, err := coll.Find( context.Background(), bson.D{ {"dim_cm", bson.D{ {"$elemMatch", bson.D{ {"$gt", 22}, {"$lt", 30}, }}, }}, }) // End Example 26 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 27 cursor, err := coll.Find( context.Background(), bson.D{ {"dim_cm.1", bson.D{ {"$gt", 25}, }}, }) // End Example 27 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 28 cursor, err := coll.Find( context.Background(), bson.D{ {"tags", bson.D{ {"$size", 3}, }}, }) // End Example 28 require.NoError(t, err) requireCursorLength(t, cursor, 1) } } // QueryArrayEmbeddedDocumentsExamples contains examples for querying fields with arrays and embedded documents. func QueryArrayEmbeddedDocumentsExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_query_array_embedded") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 29 docs := []interface{}{ bson.D{ {"item", "journal"}, {"instock", bson.A{ bson.D{ {"warehouse", "A"}, {"qty", 5}, }, bson.D{ {"warehouse", "C"}, {"qty", 15}, }, }}, }, bson.D{ {"item", "notebook"}, {"instock", bson.A{ bson.D{ {"warehouse", "C"}, {"qty", 5}, }, }}, }, bson.D{ {"item", "paper"}, {"instock", bson.A{ bson.D{ {"warehouse", "A"}, {"qty", 60}, }, bson.D{ {"warehouse", "B"}, {"qty", 15}, }, }}, }, bson.D{ {"item", "planner"}, {"instock", bson.A{ bson.D{ {"warehouse", "A"}, {"qty", 40}, }, bson.D{ {"warehouse", "B"}, {"qty", 5}, }, }}, }, bson.D{ {"item", "postcard"}, {"instock", bson.A{ bson.D{ {"warehouse", "B"}, {"qty", 15}, }, bson.D{ {"warehouse", "C"}, {"qty", 35}, }, }}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 29 require.NoError(t, err) require.Len(t, result.InsertedIDs, 5) } { // Start Example 30 cursor, err := coll.Find( context.Background(), bson.D{ {"instock", bson.D{ {"warehouse", "A"}, {"qty", 5}, }}, }) // End Example 30 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 31 cursor, err := coll.Find( context.Background(), bson.D{ {"instock", bson.D{ {"qty", 5}, {"warehouse", "A"}, }}, }) // End Example 31 require.NoError(t, err) requireCursorLength(t, cursor, 0) } { // Start Example 32 cursor, err := coll.Find( context.Background(), bson.D{ {"instock.0.qty", bson.D{ {"$lte", 20}, }}, }) // End Example 32 require.NoError(t, err) requireCursorLength(t, cursor, 3) } { // Start Example 33 cursor, err := coll.Find( context.Background(), bson.D{ {"instock.qty", bson.D{ {"$lte", 20}, }}, }) // End Example 33 require.NoError(t, err) requireCursorLength(t, cursor, 5) } { // Start Example 34 cursor, err := coll.Find( context.Background(), bson.D{ {"instock", bson.D{ {"$elemMatch", bson.D{ {"qty", 5}, {"warehouse", "A"}, }}, }}, }) // End Example 34 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 35 cursor, err := coll.Find( context.Background(), bson.D{ {"instock", bson.D{ {"$elemMatch", bson.D{ {"qty", bson.D{ {"$gt", 10}, {"$lte", 20}, }}, }}, }}, }) // End Example 35 require.NoError(t, err) requireCursorLength(t, cursor, 3) } { // Start Example 36 cursor, err := coll.Find( context.Background(), bson.D{ {"instock.qty", bson.D{ {"$gt", 10}, {"$lte", 20}, }}, }) // End Example 36 require.NoError(t, err) requireCursorLength(t, cursor, 4) } { // Start Example 37 cursor, err := coll.Find( context.Background(), bson.D{ {"instock.qty", 5}, {"instock.warehouse", "A"}, }) // End Example 37 require.NoError(t, err) requireCursorLength(t, cursor, 2) } } // QueryNullMissingFieldsExamples contains examples for querying fields that are null or missing. func QueryNullMissingFieldsExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_query_null_missing") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 38 docs := []interface{}{ bson.D{ {"_id", 1}, {"item", nil}, }, bson.D{ {"_id", 2}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 38 require.NoError(t, err) require.Len(t, result.InsertedIDs, 2) } { // Start Example 39 cursor, err := coll.Find( context.Background(), bson.D{ {"item", nil}, }) // End Example 39 require.NoError(t, err) requireCursorLength(t, cursor, 2) } { // Start Example 40 cursor, err := coll.Find( context.Background(), bson.D{ {"item", bson.D{ {"$type", 10}, }}, }) // End Example 40 require.NoError(t, err) requireCursorLength(t, cursor, 1) } { // Start Example 41 cursor, err := coll.Find( context.Background(), bson.D{ {"item", bson.D{ {"$exists", false}, }}, }) // End Example 41 require.NoError(t, err) requireCursorLength(t, cursor, 1) } } // ProjectionExamples contains examples for specifying projections in find operations. func ProjectionExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_project") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 42 docs := []interface{}{ bson.D{ {"item", "journal"}, {"status", "A"}, {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, {"instock", bson.A{ bson.D{ {"warehouse", "A"}, {"qty", 5}, }, }}, }, bson.D{ {"item", "notebook"}, {"status", "A"}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"instock", bson.A{ bson.D{ {"warehouse", "EC"}, {"qty", 5}, }, }}, }, bson.D{ {"item", "paper"}, {"status", "D"}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"instock", bson.A{ bson.D{ {"warehouse", "A"}, {"qty", 60}, }, }}, }, bson.D{ {"item", "planner"}, {"status", "D"}, {"size", bson.D{ {"h", 22.85}, {"w", 30}, {"uom", "cm"}, }}, {"instock", bson.A{ bson.D{ {"warehouse", "A"}, {"qty", 40}, }, }}, }, bson.D{ {"item", "postcard"}, {"status", "A"}, {"size", bson.D{ {"h", 10}, {"w", 15.25}, {"uom", "cm"}, }}, {"instock", bson.A{ bson.D{ {"warehouse", "B"}, {"qty", 15}, }, bson.D{ {"warehouse", "EC"}, {"qty", 35}, }, }}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 42 require.NoError(t, err) require.Len(t, result.InsertedIDs, 5) } { // Start Example 43 cursor, err := coll.Find( context.Background(), bson.D{{"status", "A"}}, ) // End Example 43 require.NoError(t, err) requireCursorLength(t, cursor, 3) } { // Start Example 44 projection := bson.D{ {"item", 1}, {"status", 1}, } cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, }, options.Find().SetProjection(projection), ) // End Example 44 require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current require.True(t, containsKey(doc, "_id")) require.True(t, containsKey(doc, "item")) require.True(t, containsKey(doc, "status")) require.False(t, containsKey(doc, "size")) require.False(t, containsKey(doc, "instock")) } require.NoError(t, cursor.Err()) } { // Start Example 45 projection := bson.D{ {"item", 1}, {"status", 1}, {"_id", 0}, } cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, }, options.Find().SetProjection(projection), ) // End Example 45 require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current require.False(t, containsKey(doc, "_id")) require.True(t, containsKey(doc, "item")) require.True(t, containsKey(doc, "status")) require.False(t, containsKey(doc, "size")) require.False(t, containsKey(doc, "instock")) } require.NoError(t, cursor.Err()) } { // Start Example 46 projection := bson.D{ {"status", 0}, {"instock", 0}, } cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, }, options.Find().SetProjection(projection), ) // End Example 46 require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current require.True(t, containsKey(doc, "_id")) require.True(t, containsKey(doc, "item")) require.False(t, containsKey(doc, "status")) require.True(t, containsKey(doc, "size")) require.False(t, containsKey(doc, "instock")) } require.NoError(t, cursor.Err()) } { // Start Example 47 projection := bson.D{ {"item", 1}, {"status", 1}, {"size.uom", 1}, } cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, }, options.Find().SetProjection(projection), ) // End Example 47 require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current require.True(t, containsKey(doc, "_id")) require.True(t, containsKey(doc, "item")) require.True(t, containsKey(doc, "status")) require.True(t, containsKey(doc, "size")) require.False(t, containsKey(doc, "instock")) require.True(t, containsKey(doc, "size", "uom")) require.False(t, containsKey(doc, "size", "h")) require.False(t, containsKey(doc, "size", "w")) } require.NoError(t, cursor.Err()) } { // Start Example 48 projection := bson.D{ {"size.uom", 0}, } cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, }, options.Find().SetProjection(projection), ) // End Example 48 require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current require.True(t, containsKey(doc, "_id")) require.True(t, containsKey(doc, "item")) require.True(t, containsKey(doc, "status")) require.True(t, containsKey(doc, "size")) require.True(t, containsKey(doc, "instock")) require.False(t, containsKey(doc, "size", "uom")) require.True(t, containsKey(doc, "size", "h")) require.True(t, containsKey(doc, "size", "w")) } require.NoError(t, cursor.Err()) } { // Start Example 49 projection := bson.D{ {"item", 1}, {"status", 1}, {"instock.qty", 1}, } cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, }, options.Find().SetProjection(projection), ) // End Example 49 require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current require.True(t, containsKey(doc, "_id")) require.True(t, containsKey(doc, "item")) require.True(t, containsKey(doc, "status")) require.False(t, containsKey(doc, "size")) require.True(t, containsKey(doc, "instock")) instock, err := doc.LookupErr("instock") require.NoError(t, err) vals, err := instock.Array().Values() require.NoError(t, err) for _, val := range vals { require.Equal(t, bson.TypeEmbeddedDocument, val.Type) subdoc := val.Document() elems, err := subdoc.Elements() require.NoError(t, err) require.Equal(t, 1, len(elems)) _, err = subdoc.LookupErr("qty") require.NoError(t, err) } } require.NoError(t, cursor.Err()) } { // Start Example 50 projection := bson.D{ {"item", 1}, {"status", 1}, {"instock", bson.D{ {"$slice", -1}, }}, } cursor, err := coll.Find( context.Background(), bson.D{ {"status", "A"}, }, options.Find().SetProjection(projection), ) // End Example 50 require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current require.True(t, containsKey(doc, "_id")) require.True(t, containsKey(doc, "item")) require.True(t, containsKey(doc, "status")) require.False(t, containsKey(doc, "size")) require.True(t, containsKey(doc, "instock")) instock, err := doc.LookupErr("instock") require.NoError(t, err) vals, err := instock.Array().Values() require.NoError(t, err) require.Equal(t, len(vals), 1) } require.NoError(t, cursor.Err()) } } // UpdateExamples contains examples of update operations. func UpdateExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_update") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 51 docs := []interface{}{ bson.D{ {"item", "canvas"}, {"qty", 100}, {"size", bson.D{ {"h", 28}, {"w", 35.5}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "journal"}, {"qty", 25}, {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "mat"}, {"qty", 85}, {"size", bson.D{ {"h", 27.9}, {"w", 35.5}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "mousepad"}, {"qty", 25}, {"size", bson.D{ {"h", 19}, {"w", 22.85}, {"uom", "in"}, }}, {"status", "P"}, }, bson.D{ {"item", "notebook"}, {"qty", 50}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "P"}, }, bson.D{ {"item", "paper"}, {"qty", 100}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "D"}, }, bson.D{ {"item", "planner"}, {"qty", 75}, {"size", bson.D{ {"h", 22.85}, {"w", 30}, {"uom", "cm"}, }}, {"status", "D"}, }, bson.D{ {"item", "postcard"}, {"qty", 45}, {"size", bson.D{ {"h", 10}, {"w", 15.25}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "sketchbook"}, {"qty", 80}, {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "sketch pad"}, {"qty", 95}, {"size", bson.D{ {"h", 22.85}, {"w", 30.5}, {"uom", "cm"}, }}, {"status", "A"}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 51 require.NoError(t, err) require.Len(t, result.InsertedIDs, 10) } { // Start Example 52 result, err := coll.UpdateOne( context.Background(), bson.D{ {"item", "paper"}, }, bson.D{ {"$set", bson.D{ {"size.uom", "cm"}, {"status", "P"}, }}, {"$currentDate", bson.D{ {"lastModified", true}, }}, }, ) // End Example 52 require.NoError(t, err) require.Equal(t, int64(1), result.MatchedCount) require.Equal(t, int64(1), result.ModifiedCount) cursor, err := coll.Find( context.Background(), bson.D{ {"item", "paper"}, }) require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current uom, err := doc.LookupErr("size", "uom") require.NoError(t, err) require.Equal(t, uom.StringValue(), "cm") status, err := doc.LookupErr("status") require.NoError(t, err) require.Equal(t, status.StringValue(), "P") require.True(t, containsKey(doc, "lastModified")) } require.NoError(t, cursor.Err()) } { // Start Example 53 result, err := coll.UpdateMany( context.Background(), bson.D{ {"qty", bson.D{ {"$lt", 50}, }}, }, bson.D{ {"$set", bson.D{ {"size.uom", "cm"}, {"status", "P"}, }}, {"$currentDate", bson.D{ {"lastModified", true}, }}, }, ) // End Example 53 require.NoError(t, err) require.Equal(t, int64(3), result.MatchedCount) require.Equal(t, int64(3), result.ModifiedCount) cursor, err := coll.Find( context.Background(), bson.D{ {"qty", bson.D{ {"$lt", 50}, }}, }) require.NoError(t, err) for cursor.Next(context.Background()) { doc := cursor.Current uom, err := doc.LookupErr("size", "uom") require.NoError(t, err) require.Equal(t, uom.StringValue(), "cm") status, err := doc.LookupErr("status") require.NoError(t, err) require.Equal(t, status.StringValue(), "P") require.True(t, containsKey(doc, "lastModified")) } require.NoError(t, cursor.Err()) } { // Start Example 54 result, err := coll.ReplaceOne( context.Background(), bson.D{ {"item", "paper"}, }, bson.D{ {"item", "paper"}, {"instock", bson.A{ bson.D{ {"warehouse", "A"}, {"qty", 60}, }, bson.D{ {"warehouse", "B"}, {"qty", 40}, }, }}, }, ) // End Example 54 require.NoError(t, err) require.Equal(t, int64(1), result.MatchedCount) require.Equal(t, int64(1), result.ModifiedCount) cursor, err := coll.Find( context.Background(), bson.D{ {"item", "paper"}, }) require.NoError(t, err) for cursor.Next(context.Background()) { require.True(t, containsKey(cursor.Current, "_id")) require.True(t, containsKey(cursor.Current, "item")) require.True(t, containsKey(cursor.Current, "instock")) instock, err := cursor.Current.LookupErr("instock") require.NoError(t, err) vals, err := instock.Array().Values() require.NoError(t, err) require.Equal(t, len(vals), 2) } require.NoError(t, cursor.Err()) } } // DeleteExamples contains examples of delete operations. func DeleteExamples(t *testing.T, db *mongo.Database) { coll := db.Collection("inventory_delete") err := coll.Drop(context.Background()) require.NoError(t, err) { // Start Example 55 docs := []interface{}{ bson.D{ {"item", "journal"}, {"qty", 25}, {"size", bson.D{ {"h", 14}, {"w", 21}, {"uom", "cm"}, }}, {"status", "A"}, }, bson.D{ {"item", "notebook"}, {"qty", 50}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "P"}, }, bson.D{ {"item", "paper"}, {"qty", 100}, {"size", bson.D{ {"h", 8.5}, {"w", 11}, {"uom", "in"}, }}, {"status", "D"}, }, bson.D{ {"item", "planner"}, {"qty", 75}, {"size", bson.D{ {"h", 22.85}, {"w", 30}, {"uom", "cm"}, }}, {"status", "D"}, }, bson.D{ {"item", "postcard"}, {"qty", 45}, {"size", bson.D{ {"h", 10}, {"w", 15.25}, {"uom", "cm"}, }}, {"status", "A"}, }, } result, err := coll.InsertMany(context.Background(), docs) // End Example 55 require.NoError(t, err) require.Len(t, result.InsertedIDs, 5) } { // Start Example 57 result, err := coll.DeleteMany( context.Background(), bson.D{ {"status", "A"}, }, ) // End Example 57 require.NoError(t, err) require.Equal(t, int64(2), result.DeletedCount) } { // Start Example 58 result, err := coll.DeleteOne( context.Background(), bson.D{ {"status", "D"}, }, ) // End Example 58 require.NoError(t, err) require.Equal(t, int64(1), result.DeletedCount) } { // Start Example 56 result, err := coll.DeleteMany(context.Background(), bson.D{}) // End Example 56 require.NoError(t, err) require.Equal(t, int64(2), result.DeletedCount) } } var log = logger.New(ioutil.Discard, "", logger.LstdFlags) // Start Transactions Intro Example 1 // UpdateEmployeeInfo is an example function demonstrating transactions. func UpdateEmployeeInfo(ctx context.Context, client *mongo.Client) error { employees := client.Database("hr").Collection("employees") events := client.Database("reporting").Collection("events") return client.UseSession(ctx, func(sctx mongo.SessionContext) error { err := sctx.StartTransaction(options.Transaction(). SetReadConcern(readconcern.Snapshot()). SetWriteConcern(writeconcern.New(writeconcern.WMajority())), ) if err != nil { return err } _, err = employees.UpdateOne(sctx, bson.D{{"employee", 3}}, bson.D{{"$set", bson.D{{"status", "Inactive"}}}}) if err != nil { sctx.AbortTransaction(sctx) log.Println("caught exception during transaction, aborting.") return err } _, err = events.InsertOne(sctx, bson.D{{"employee", 3}, {"status", bson.D{{"new", "Inactive"}, {"old", "Active"}}}}) if err != nil { sctx.AbortTransaction(sctx) log.Println("caught exception during transaction, aborting.") return err } for { err = sctx.CommitTransaction(sctx) switch e := err.(type) { case nil: return nil case mongo.CommandError: if e.HasErrorLabel("UnknownTransactionCommitResult") { log.Println("UnknownTransactionCommitResult, retrying commit operation...") continue } log.Println("Error during commit...") return e default: log.Println("Error during commit...") return e } } }) } // End Transactions Intro Example 1 // Start Transactions Retry Example 1 // RunTransactionWithRetry is an example function demonstrating transaction retry logic. func RunTransactionWithRetry(sctx mongo.SessionContext, txnFn func(mongo.SessionContext) error) error { for { err := txnFn(sctx) // Performs transaction. if err == nil { return nil } log.Println("Transaction aborted. Caught exception during transaction.") // If transient error, retry the whole transaction if cmdErr, ok := err.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") { log.Println("TransientTransactionError, retrying transaction...") continue } return err } } // End Transactions Retry Example 1 // Start Transactions Retry Example 2 // CommitWithRetry is an example function demonstrating transaction commit with retry logic. func CommitWithRetry(sctx mongo.SessionContext) error { for { err := sctx.CommitTransaction(sctx) switch e := err.(type) { case nil: log.Println("Transaction committed.") return nil case mongo.CommandError: // Can retry commit if e.HasErrorLabel("UnknownTransactionCommitResult") { log.Println("UnknownTransactionCommitResult, retrying commit operation...") continue } log.Println("Error during commit...") return e default: log.Println("Error during commit...") return e } } } // End Transactions Retry Example 2 // TransactionsExamples contains examples for transaction operations. func TransactionsExamples(ctx context.Context, client *mongo.Client) error { _, err := client.Database("hr").Collection("employees").InsertOne(ctx, bson.D{{"pi", 3.14159}}) if err != nil { return err } _, err = client.Database("hr").Collection("employees").DeleteOne(ctx, bson.D{{"pi", 3.14159}}) if err != nil { return err } _, err = client.Database("reporting").Collection("events").InsertOne(ctx, bson.D{{"pi", 3.14159}}) if err != nil { return err } _, err = client.Database("reporting").Collection("events").DeleteOne(ctx, bson.D{{"pi", 3.14159}}) if err != nil { return err } // Start Transactions Retry Example 3 runTransactionWithRetry := func(sctx mongo.SessionContext, txnFn func(mongo.SessionContext) error) error { for { err := txnFn(sctx) // Performs transaction. if err == nil { return nil } log.Println("Transaction aborted. Caught exception during transaction.") // If transient error, retry the whole transaction if cmdErr, ok := err.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") { log.Println("TransientTransactionError, retrying transaction...") continue } return err } } commitWithRetry := func(sctx mongo.SessionContext) error { for { err := sctx.CommitTransaction(sctx) switch e := err.(type) { case nil: log.Println("Transaction committed.") return nil case mongo.CommandError: // Can retry commit if e.HasErrorLabel("UnknownTransactionCommitResult") { log.Println("UnknownTransactionCommitResult, retrying commit operation...") continue } log.Println("Error during commit...") return e default: log.Println("Error during commit...") return e } } } // Updates two collections in a transaction. updateEmployeeInfo := func(sctx mongo.SessionContext) error { employees := client.Database("hr").Collection("employees") events := client.Database("reporting").Collection("events") err := sctx.StartTransaction(options.Transaction(). SetReadConcern(readconcern.Snapshot()). SetWriteConcern(writeconcern.New(writeconcern.WMajority())), ) if err != nil { return err } _, err = employees.UpdateOne(sctx, bson.D{{"employee", 3}}, bson.D{{"$set", bson.D{{"status", "Inactive"}}}}) if err != nil { sctx.AbortTransaction(sctx) log.Println("caught exception during transaction, aborting.") return err } _, err = events.InsertOne(sctx, bson.D{{"employee", 3}, {"status", bson.D{{"new", "Inactive"}, {"old", "Active"}}}}) if err != nil { sctx.AbortTransaction(sctx) log.Println("caught exception during transaction, aborting.") return err } return commitWithRetry(sctx) } return client.UseSessionWithOptions( ctx, options.Session().SetDefaultReadPreference(readpref.Primary()), func(sctx mongo.SessionContext) error { return runTransactionWithRetry(sctx, updateEmployeeInfo) }, ) } // End Transactions Retry Example 3 // Start Transactions withTxn API Example 1 // WithTransactionExample is an example of using the Session.WithTransaction function. func WithTransactionExample() { ctx := context.Background() // For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g. // uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl" // For a sharded cluster, connect to the mongos instances; e.g. // uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/" var uri string clientOpts := options.Client().ApplyURI(uri) client, err := mongo.Connect(ctx, clientOpts) if err != nil { panic(err) } defer func() { _ = client.Disconnect(ctx) }() // Prereq: Create collections. wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second)) wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority) fooColl := client.Database("mydb1").Collection("foo", wcMajorityCollectionOpts) barColl := client.Database("mydb1").Collection("bar", wcMajorityCollectionOpts) // Step 1: Define the callback that specifies the sequence of operations to perform inside the transaction. callback := func(sessCtx mongo.SessionContext) (interface{}, error) { // Important: You must pass sessCtx as the Context parameter to the operations for them to be executed in the // transaction. if _, err := fooColl.InsertOne(sessCtx, bson.D{{"abc", 1}}); err != nil { return nil, err } if _, err := barColl.InsertOne(sessCtx, bson.D{{"xyz", 999}}); err != nil { return nil, err } return nil, nil } // Step 2: Start a session and run the callback using WithTransaction. session, err := client.StartSession() if err != nil { panic(err) } defer session.EndSession(ctx) result, err := session.WithTransaction(ctx, callback) if err != nil { panic(err) } fmt.Printf("result: %v\n", result) } // End Transactions withTxn API Example 1 // ChangeStreamExamples contains examples of changestream operations. func ChangeStreamExamples(t *testing.T, db *mongo.Database) { ctx := context.Background() coll := db.Collection("inventory_changestream") err := coll.Drop(context.Background()) require.NoError(t, err) _, err = coll.InsertOne(ctx, bson.D{{"x", int32(1)}}) require.NoError(t, err) var stop int32 doInserts := func(coll *mongo.Collection) { for atomic.LoadInt32(&stop) == 0 { _, err = coll.InsertOne(ctx, bson.D{{"x", 1}}) time.Sleep(10 * time.Millisecond) coll.DeleteOne(ctx, bson.D{{"x", 1}}) } } go doInserts(coll) { // Start Changestream Example 1 cs, err := coll.Watch(ctx, mongo.Pipeline{}) require.NoError(t, err) defer cs.Close(ctx) ok := cs.Next(ctx) next := cs.Current // End Changestream Example 1 require.True(t, ok) require.NoError(t, err) require.NotEqual(t, len(next), 0) } { // Start Changestream Example 2 cs, err := coll.Watch(ctx, mongo.Pipeline{}, options.ChangeStream().SetFullDocument(options.UpdateLookup)) require.NoError(t, err) defer cs.Close(ctx) ok := cs.Next(ctx) next := cs.Current // End Changestream Example 2 require.True(t, ok) require.NoError(t, err) require.NotEqual(t, len(next), 0) } { original, err := coll.Watch(ctx, mongo.Pipeline{}) require.NoError(t, err) defer original.Close(ctx) ok := original.Next(ctx) require.True(t, ok) // Start Changestream Example 3 resumeToken := original.ResumeToken() cs, err := coll.Watch(ctx, mongo.Pipeline{}, options.ChangeStream().SetResumeAfter(resumeToken)) require.NoError(t, err) defer cs.Close(ctx) ok = cs.Next(ctx) result := cs.Current // End Changestream Example 3 require.True(t, ok) require.NoError(t, err) require.NotEqual(t, len(result), 0) } { // Start Changestream Example 4 pipeline := mongo.Pipeline{bson.D{{"$match", bson.D{{"$or", bson.A{ bson.D{{"fullDocument.username", "alice"}}, bson.D{{"operationType", "delete"}}}}}, }}} cs, err := coll.Watch(ctx, pipeline) require.NoError(t, err) defer cs.Close(ctx) ok := cs.Next(ctx) next := cs.Current // End Changestream Example 4 require.True(t, ok) require.NoError(t, err) require.NotEqual(t, len(next), 0) } atomic.StoreInt32(&stop, 1) } // AggregationExamples contains examples of aggregation operations. func AggregationExamples(t *testing.T, db *mongo.Database) { ctx := context.Background() salesColl := db.Collection("sales") airlinesColl := db.Collection("airlines") airAlliancesColl := db.Collection("air_alliances") err := salesColl.Drop(ctx) require.NoError(t, err) err = airlinesColl.Drop(ctx) require.NoError(t, err) err = airAlliancesColl.Drop(ctx) require.NoError(t, err) date20180208 := parseDate(t, "2018-02-08T09:00:00.000Z") date20180109 := parseDate(t, "2018-01-09T07:12:00.000Z") date20180127 := parseDate(t, "2018-01-27T09:13:00.000Z") date20180203 := parseDate(t, "2018-02-03T07:58:00.000Z") date20180205 := parseDate(t, "2018-02-05T06:03:00.000Z") date20180111 := parseDate(t, "2018-01-11T07:15:00.000Z") sales := []interface{}{ bson.D{ {"date", date20180208}, {"items", bson.A{ bson.D{ {"fruit", "kiwi"}, {"quantity", 2}, {"price", 0.5}, }, bson.D{ {"fruit", "apple"}, {"quantity", 1}, {"price", 1.0}, }, }}, }, bson.D{ {"date", date20180109}, {"items", bson.A{ bson.D{ {"fruit", "banana"}, {"quantity", 8}, {"price", 1.0}, }, bson.D{ {"fruit", "apple"}, {"quantity", 1}, {"price", 1.0}, }, bson.D{ {"fruit", "papaya"}, {"quantity", 1}, {"price", 4.0}, }, }}, }, bson.D{ {"date", date20180127}, {"items", bson.A{ bson.D{ {"fruit", "banana"}, {"quantity", 1}, {"price", 1.0}, }, }}, }, bson.D{ {"date", date20180203}, {"items", bson.A{ bson.D{ {"fruit", "banana"}, {"quantity", 1}, {"price", 1.0}, }, }}, }, bson.D{ {"date", date20180205}, {"items", bson.A{ bson.D{ {"fruit", "banana"}, {"quantity", 1}, {"price", 1.0}, }, bson.D{ {"fruit", "mango"}, {"quantity", 2}, {"price", 2.0}, }, bson.D{ {"fruit", "apple"}, {"quantity", 1}, {"price", 1.0}, }, }}, }, bson.D{ {"date", date20180111}, {"items", bson.A{ bson.D{ {"fruit", "banana"}, {"quantity", 1}, {"price", 1.0}, }, bson.D{ {"fruit", "apple"}, {"quantity", 1}, {"price", 1.0}, }, bson.D{ {"fruit", "papaya"}, {"quantity", 3}, {"price", 4.0}, }, }}, }, } airlines := []interface{}{ bson.D{ {"airline", 17}, {"name", "Air Canada"}, {"alias", "AC"}, {"iata", "ACA"}, {"icao", "AIR CANADA"}, {"active", "Y"}, {"country", "Canada"}, {"base", "TAL"}, }, bson.D{ {"airline", 18}, {"name", "Turkish Airlines"}, {"alias", "YK"}, {"iata", "TRK"}, {"icao", "TURKISH"}, {"active", "Y"}, {"country", "Turkey"}, {"base", "AET"}, }, bson.D{ {"airline", 22}, {"name", "Saudia"}, {"alias", "SV"}, {"iata", "SVA"}, {"icao", "SAUDIA"}, {"active", "Y"}, {"country", "Saudi Arabia"}, {"base", "JSU"}, }, bson.D{ {"airline", 29}, {"name", "Finnair"}, {"alias", "AY"}, {"iata", "FIN"}, {"icao", "FINNAIR"}, {"active", "Y"}, {"country", "Finland"}, {"base", "JMZ"}, }, bson.D{ {"airline", 34}, {"name", "Afric'air Express"}, {"alias", ""}, {"iata", "AAX"}, {"icao", "AFREX"}, {"active", "N"}, {"country", "Ivory Coast"}, {"base", "LOK"}, }, bson.D{ {"airline", 37}, {"name", "Artem-Avia"}, {"alias", ""}, {"iata", "ABA"}, {"icao", "ARTEM-AVIA"}, {"active", "N"}, {"country", "Ukraine"}, {"base", "JBR"}, }, bson.D{ {"airline", 38}, {"name", "Lufthansa"}, {"alias", "LH"}, {"iata", "DLH"}, {"icao", "LUFTHANSA"}, {"active", "Y"}, {"country", "Germany"}, {"base", "CYS"}, }, } airAlliances := []interface{}{ bson.D{ {"name", "Star Alliance"}, {"airlines", bson.A{ "Air Canada", "Avianca", "Air China", "Air New Zealand", "Asiana Airlines", "Brussels Airlines", "Copa Airlines", "Croatia Airlines", "EgyptAir", "TAP Portugal", "United Airlines", "Turkish Airlines", "Swiss International Air Lines", "Lufthansa", }}, }, bson.D{ {"name", "SkyTeam"}, {"airlines", bson.A{ "Aerolinias Argentinas", "Aeromexico", "Air Europa", "Air France", "Alitalia", "Delta Air Lines", "Garuda Indonesia", "Kenya Airways", "KLM", "Korean Air", "Middle East Airlines", "Saudia", }}, }, bson.D{ {"name", "OneWorld"}, {"airlines", bson.A{ "Air Berlin", "American Airlines", "British Airways", "Cathay Pacific", "Finnair", "Iberia Airlines", "Japan Airlines", "LATAM Chile", "LATAM Brasil", "Malasya Airlines", "Canadian Airlines", }}, }, } salesResult, salesErr := salesColl.InsertMany(ctx, sales) airlinesResult, airlinesErr := airlinesColl.InsertMany(ctx, airlines) airAlliancesResult, airAlliancesErr := airAlliancesColl.InsertMany(ctx, airAlliances) require.NoError(t, salesErr) require.Len(t, salesResult.InsertedIDs, 6) require.NoError(t, airlinesErr) require.Len(t, airlinesResult.InsertedIDs, 7) require.NoError(t, airAlliancesErr) require.Len(t, airAlliancesResult.InsertedIDs, 3) { // Start Aggregation Example 1 pipeline := mongo.Pipeline{ { {"$match", bson.D{ {"items.fruit", "banana"}, }}, }, { {"$sort", bson.D{ {"date", 1}, }}, }, } cursor, err := salesColl.Aggregate(ctx, pipeline) // End Aggregation Example 1 require.NoError(t, err) defer cursor.Close(ctx) requireCursorLength(t, cursor, 5) } { // Start Aggregation Example 2 pipeline := mongo.Pipeline{ { {"$unwind", "$items"}, }, { {"$match", bson.D{ {"items.fruit", "banana"}, }}, }, { {"$group", bson.D{ {"_id", bson.D{ {"day", bson.D{ {"$dayOfWeek", "$date"}, }}, }}, {"count", bson.D{ {"$sum", "$items.quantity"}, }}, }}, }, { {"$project", bson.D{ {"dayOfWeek", "$_id.day"}, {"numberSold", "$count"}, {"_id", 0}, }}, }, { {"$sort", bson.D{ {"numberSold", 1}, }}, }, } cursor, err := salesColl.Aggregate(ctx, pipeline) // End Aggregation Example 2 require.NoError(t, err) defer cursor.Close(ctx) requireCursorLength(t, cursor, 4) } { // Start Aggregation Example 3 pipeline := mongo.Pipeline{ { {"$unwind", "$items"}, }, { {"$group", bson.D{ {"_id", bson.D{ {"day", bson.D{ {"$dayOfWeek", "$date"}, }}, }}, {"items_sold", bson.D{ {"$sum", "$items.quantity"}, }}, {"revenue", bson.D{ {"$sum", bson.D{ {"$multiply", bson.A{"$items.quantity", "$items.price"}}, }}, }}, }}, }, { {"$project", bson.D{ {"day", "$_id.day"}, {"revenue", 1}, {"items_sold", 1}, {"discount", bson.D{ {"$cond", bson.D{ {"if", bson.D{ {"$lte", bson.A{"$revenue", 250}}, }}, {"then", 25}, {"else", 0}, }}, }}, }}, }, } cursor, err := salesColl.Aggregate(ctx, pipeline) // End Aggregation Example 3 require.NoError(t, err) defer cursor.Close(ctx) requireCursorLength(t, cursor, 4) } { // Start Aggregation Example 4 pipeline := mongo.Pipeline{ { {"$lookup", bson.D{ {"from", "air_airlines"}, {"let", bson.D{ {"constituents", "$airlines"}}, }, {"pipeline", bson.A{bson.D{ {"$match", bson.D{ {"$expr", bson.D{ {"$in", bson.A{"$name", "$$constituents"}}, }}, }}, }}}, {"as", "airlines"}, }}, }, { {"$project", bson.D{ {"_id", 0}, {"name", 1}, {"airlines", bson.D{ {"$filter", bson.D{ {"input", "$airlines"}, {"as", "airline"}, {"cond", bson.D{ {"$eq", bson.A{"$$airline.country", "Canada"}}, }}, }}, }}, }}, }, } cursor, err := airAlliancesColl.Aggregate(ctx, pipeline) // End Aggregation Example 4 require.NoError(t, err) defer cursor.Close(ctx) requireCursorLength(t, cursor, 3) } } // CausalConsistencyExamples contains examples of causal consistency usage. func CausalConsistencyExamples(client *mongo.Client) error { ctx := context.Background() coll := client.Database("test").Collection("items") currentDate := time.Now() err := coll.Drop(ctx) if err != nil { return err } // Start Causal Consistency Example 1 // Use a causally-consistent session to run some operations opts := options.Session().SetDefaultReadConcern(readconcern.Majority()).SetDefaultWriteConcern( writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1000))) session1, err := client.StartSession(opts) if err != nil { return err } err = client.UseSessionWithOptions(context.TODO(), opts, func(sctx mongo.SessionContext) error { // Run an update with our causally-consistent session _, err = coll.UpdateOne(sctx, bson.D{{"sku", 111}}, bson.D{{"$set", bson.D{{"end", currentDate}}}}) if err != nil { return err } // Run an insert with our causally-consistent session _, err = coll.InsertOne(sctx, bson.D{{"sku", "nuts-111"}, {"name", "Pecans"}, {"start", currentDate}}) if err != nil { return err } return nil }) if err != nil { return err } // End Causal Consistency Example 1 // Start Causal Consistency Example 2 // Make a new session that is causally consistent with session1 so session2 reads what session1 writes opts = options.Session().SetDefaultReadPreference(readpref.Secondary()).SetDefaultReadConcern( readconcern.Majority()).SetDefaultWriteConcern(writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1000))) session2, err := client.StartSession(opts) if err != nil { return err } err = client.UseSessionWithOptions(context.TODO(), opts, func(sctx mongo.SessionContext) error { // Set cluster time of session2 to session1's cluster time clusterTime := session1.ClusterTime() session2.AdvanceClusterTime(clusterTime) // Set operation time of session2 to session1's operation time operationTime := session1.OperationTime() session2.AdvanceOperationTime(operationTime) // Run a find on session2, which should find all the writes from session1 cursor, err := coll.Find(sctx, bson.D{{"end", nil}}) if err != nil { return err } for cursor.Next(sctx) { doc := cursor.Current fmt.Printf("Document: %v\n", doc.String()) } return cursor.Err() }) if err != nil { return err } // End Causal Consistency Example 2 return nil } // RunCommandExamples contains examples of RunCommand operations. func RunCommandExamples(t *testing.T, db *mongo.Database) { ctx := context.Background() coll := db.Collection("restaurants") err := coll.Drop(ctx) require.NoError(t, err) restaurants := []interface{}{ bson.D{ {"name", "Chez Panisse"}, {"city", "Oakland"}, {"state", "California"}, {"country", "United States"}, {"rating", 4.4}, }, bson.D{ {"name", "Central"}, {"city", "Lima"}, {"country", "Peru"}, {"rating", 4.8}, }, bson.D{ {"name", "Eleven Madison Park"}, {"city", "New York City"}, {"state", "New York"}, {"country", "United States"}, {"rating", 4.6}, }, bson.D{ {"name", "Gaggan"}, {"city", "Bangkok"}, {"country", "Thailand"}, {"rating", 4.3}, }, bson.D{ {"name", "Dad's Grill"}, {"city", "Oklahoma City"}, {"state", "Oklahoma"}, {"country", "United States"}, {"rating", 2.1}, }, } result, err := coll.InsertMany(ctx, restaurants) require.NoError(t, err) require.Len(t, result.InsertedIDs, 5) { // Start RunCommand Example 1 res := db.RunCommand(ctx, bson.D{{"buildInfo", 1}}) // End RunCommand Example 1 err := res.Err() require.NoError(t, err) } { // Start RunCommand Example 2 res := db.RunCommand(ctx, bson.D{{"collStats", "restaurants"}}) // End RunCommand Example 2 err := res.Err() require.NoError(t, err) } } // IndexExamples contains examples of Index operations. func IndexExamples(t *testing.T, db *mongo.Database) { ctx := context.Background() recordsColl := db.Collection("records") restaurantsColl := db.Collection("restaurants") err := recordsColl.Drop(ctx) require.NoError(t, err) err = restaurantsColl.Drop(ctx) require.NoError(t, err) records := []interface{}{ bson.D{ {"student", "Marty McFly"}, {"classYear", 1986}, {"school", "Hill Valley High"}, {"score", 56.5}, }, bson.D{ {"student", "Ferris F. Bueller"}, {"classYear", 1987}, {"school", "Glenbrook North High"}, {"status", "Suspended"}, {"score", 76.0}, }, bson.D{ {"student", "Reynard Muldoon"}, {"classYear", 2007}, {"school", "Stonetown Middle"}, {"score", 99.9}, }, } restaurants := []interface{}{ bson.D{ {"name", "Chez Panisse"}, {"cuisine", "American/French"}, {"city", "Oakland"}, {"state", "California"}, {"country", "United States"}, {"rating", 4.9}, }, bson.D{ {"name", "Central"}, {"cuisine", "Peruvian"}, {"city", "Lima"}, {"country", "Peru"}, {"rating", 5.8}, }, bson.D{ {"name", "Eleven Madison Park"}, {"cuisine", "French"}, {"city", "New York City"}, {"state", "New York"}, {"country", "United States"}, {"rating", 7.1}, }, bson.D{ {"name", "Gaggan"}, {"cuisine", "Thai Fusion"}, {"city", "Bangkok"}, {"country", "Thailand"}, {"rating", 9.2}, }, bson.D{ {"name", "Dad's Grill"}, {"cuisine", "BBQ"}, {"city", "Oklahoma City"}, {"state", "Oklahoma"}, {"country", "United States"}, {"rating", 2.1}, }, } recordsResult, recordsErr := recordsColl.InsertMany(ctx, records) restaurantsResult, restaurantsErr := restaurantsColl.InsertMany(ctx, restaurants) require.NoError(t, recordsErr) require.Len(t, recordsResult.InsertedIDs, 3) require.NoError(t, restaurantsErr) require.Len(t, restaurantsResult.InsertedIDs, 5) { // Start Index Example 1 indexModel := mongo.IndexModel{ Keys: bson.D{ {"score", 1}, }, } _, err := recordsColl.Indexes().CreateOne(ctx, indexModel) // End Index Example 1 require.NoError(t, err) } { // Start Index Example 2 partialFilterExpression := bson.D{ {"rating", bson.D{ {"$gt", 5}, }}, } indexModel := mongo.IndexModel{ Keys: bson.D{ {"cuisine", 1}, {"name", 1}, }, Options: options.Index().SetPartialFilterExpression(partialFilterExpression), } _, err := restaurantsColl.Indexes().CreateOne(ctx, indexModel) // End Index Example 2 require.NoError(t, err) } } // Start Versioned API Example 1 // VersionedAPIExample is an example of creating a client with versioned API. func VersionedAPIExample() { ctx := context.Background() // For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g. // uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl" // For a sharded cluster, connect to the mongos instances; e.g. // uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/" uri := "mongodb://localhost:27017" serverAPIOptions := options.ServerAPI(options.ServerAPIVersion1) clientOpts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPIOptions) client, err := mongo.Connect(ctx, clientOpts) if err != nil { panic(err) } defer func() { _ = client.Disconnect(ctx) }() } // End Versioned API Example 1 // Start Versioned API Example 2 // VersionedAPIStrictExample is an example of creating a client with strict versioned API. func VersionedAPIStrictExample() { ctx := context.Background() // For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g. // uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl" // For a sharded cluster, connect to the mongos instances; e.g. // uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/" uri := "mongodb://localhost:27017" serverAPIOptions := options.ServerAPI(options.ServerAPIVersion1).SetStrict(true) clientOpts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPIOptions) client, err := mongo.Connect(ctx, clientOpts) if err != nil { panic(err) } defer func() { _ = client.Disconnect(ctx) }() } // End Versioned API Example 2 // Start Versioned API Example 3 // VersionedAPINonStrictExample is an example of creating a client with non-strict versioned API. func VersionedAPINonStrictExample() { ctx := context.Background() // For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g. // uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl" // For a sharded cluster, connect to the mongos instances; e.g. // uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/" uri := "mongodb://localhost:27017" serverAPIOptions := options.ServerAPI(options.ServerAPIVersion1).SetStrict(false) clientOpts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPIOptions) client, err := mongo.Connect(ctx, clientOpts) if err != nil { panic(err) } defer func() { _ = client.Disconnect(ctx) }() } // End Versioned API Example 3 // Start Versioned API Example 4 // VersionedAPIDeprecationErrorsExample is an example of creating a client with versioned API // with deprecation errors. func VersionedAPIDeprecationErrorsExample() { ctx := context.Background() // For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g. // uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl" // For a sharded cluster, connect to the mongos instances; e.g. // uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/" uri := "mongodb://localhost:27017" serverAPIOptions := options.ServerAPI(options.ServerAPIVersion1).SetDeprecationErrors(true) clientOpts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPIOptions) client, err := mongo.Connect(ctx, clientOpts) if err != nil { panic(err) } defer func() { _ = client.Disconnect(ctx) }() } // End Versioned API Example 4 // VersionedAPIStrictCountExample is an example of using CountDocuments instead of a traditional count // with a strict API version since the count command does not belong to API version 1. func VersionedAPIStrictCountExample(t *testing.T) { uri := "mongodb://localhost:27017" serverAPIOptions := options.ServerAPI(options.ServerAPIVersion1).SetStrict(true) clientOpts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPIOptions) client, err := mongo.Connect(context.TODO(), clientOpts) require.Nil(t, err, "Connect error: %v", err) defer func() { _ = client.Disconnect(context.TODO()) }() // Start Versioned API Example 5 coll := client.Database("db").Collection("sales") docs := []interface{}{ bson.D{{"_id", 1}, {"item", "abc"}, {"price", 10}, {"quantity", 2}, {"date", "2021-01-01T08:00:00Z"}}, bson.D{{"_id", 2}, {"item", "jkl"}, {"price", 20}, {"quantity", 1}, {"date", "2021-02-03T09:00:00Z"}}, bson.D{{"_id", 3}, {"item", "xyz"}, {"price", 5}, {"quantity", 5}, {"date", "2021-02-03T09:05:00Z"}}, bson.D{{"_id", 4}, {"item", "abc"}, {"price", 10}, {"quantity", 10}, {"date", "2021-02-15T08:00:00Z"}}, bson.D{{"_id", 5}, {"item", "xyz"}, {"price", 5}, {"quantity", 10}, {"date", "2021-02-15T09:05:00Z"}}, bson.D{{"_id", 6}, {"item", "xyz"}, {"price", 5}, {"quantity", 5}, {"date", "2021-02-15T12:05:10Z"}}, bson.D{{"_id", 7}, {"item", "xyz"}, {"price", 5}, {"quantity", 10}, {"date", "2021-02-15T14:12:12Z"}}, bson.D{{"_id", 8}, {"item", "abc"}, {"price", 10}, {"quantity", 5}, {"date", "2021-03-16T20:20:13Z"}}, } _, err = coll.InsertMany(context.TODO(), docs) // End Versioned API Example 5 defer func() { _ = coll.Drop(context.TODO()) }() require.Nil(t, err, "InsertMany error: %v", err) res := client.Database("db").RunCommand(context.TODO(), bson.D{{"count", "sales"}}) require.NotNil(t, res.Err(), "expected RunCommand error, got nil") expectedErr := "Provided apiStrict:true, but the command count is not in API Version 1" require.True(t, strings.Contains(res.Err().Error(), expectedErr), "expected RunCommand error to contain %q, got %q", expectedErr, res.Err().Error()) // Start Versioned API Example 6 // (APIStrictError) Provided apiStrict:true, but the command count is not in API Version 1. // End Versioned API Example 6 // Start Versioned API Example 7 count, err := coll.CountDocuments(context.TODO(), bson.D{}) // End Versioned API Example 7 require.Nil(t, err, "CountDocuments error: %v", err) require.Equal(t, count, int64(8), "expected count to be 8, got %v", count) // Start Versioned API Example 8 // 8 // End Versioned API Example 8 } // VersionedAPIExamples runs all versioned API examples. func VersionedAPIExamples() { VersionedAPIExample() VersionedAPIStrictExample() VersionedAPINonStrictExample() VersionedAPIDeprecationErrorsExample() }