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 7package mongo_test 8 9import ( 10 "context" 11 "fmt" 12 "log" 13 "sync" 14 "time" 15 16 "go.mongodb.org/mongo-driver/bson" 17 "go.mongodb.org/mongo-driver/bson/primitive" 18 "go.mongodb.org/mongo-driver/mongo" 19 "go.mongodb.org/mongo-driver/mongo/options" 20 "go.mongodb.org/mongo-driver/mongo/readconcern" 21 "go.mongodb.org/mongo-driver/mongo/readpref" 22) 23 24// Client examples 25 26func ExampleClient_ListDatabaseNames() { 27 var client *mongo.Client 28 29 // use a filter to only select non-empty databases 30 result, err := client.ListDatabaseNames(context.TODO(), bson.D{{"empty", false}}) 31 if err != nil { 32 log.Fatal(err) 33 } 34 35 for _, db := range result { 36 fmt.Println(db) 37 } 38} 39 40func ExampleClient_Watch() { 41 var client *mongo.Client 42 43 // specify a pipeline that will only match "insert" events 44 // specify the MaxAwaitTimeOption to have each attempt wait two seconds for new documents 45 matchStage := bson.D{{"$match", bson.D{{"operationType", "insert"}}}} 46 opts := options.ChangeStream().SetMaxAwaitTime(2 * time.Second) 47 changeStream, err := client.Watch(context.TODO(), mongo.Pipeline{matchStage}, opts) 48 if err != nil { 49 log.Fatal(err) 50 } 51 52 // print out all change stream events in the order they're received 53 // see the mongo.ChangeStream documentation for more examples of using change streams 54 for changeStream.Next(context.TODO()) { 55 fmt.Println(changeStream.Current) 56 } 57} 58 59// Database examples 60 61func ExampleDatabase_CreateCollection() { 62 var db *mongo.Database 63 64 // Create a "users" collection with a JSON schema validator. The validator will ensure that each document in the 65 // collection has "name" and "age" fields. 66 jsonSchema := bson.M{ 67 "bsonType": "object", 68 "required": []string{"name", "age"}, 69 "properties": bson.M{ 70 "name": bson.M{ 71 "bsonType": "string", 72 "description": "the name of the user, which is required and must be a string", 73 }, 74 "age": bson.M{ 75 "bsonType": "int", 76 "minimum": 18, 77 "description": "the age of the user, which is required and must be an integer >= 18", 78 }, 79 }, 80 } 81 validator := bson.M{ 82 "$jsonSchema": jsonSchema, 83 } 84 opts := options.CreateCollection().SetValidator(validator) 85 86 if err := db.CreateCollection(context.TODO(), "users", opts); err != nil { 87 log.Fatal(err) 88 } 89} 90 91func ExampleDatabase_CreateView() { 92 var db *mongo.Database 93 94 // Create a view on the "users" collection called "usernames". Specify a pipeline that concatenates the "firstName" 95 // and "lastName" fields from each document in "users" and projects the result into the "fullName" field in the 96 // view. 97 projectStage := bson.D{ 98 {"$project", bson.D{ 99 {"_id", 0}, 100 {"fullName", bson.D{ 101 {"$concat", []string{"$firstName", " ", "$lastName"}}, 102 }}, 103 }}, 104 } 105 pipeline := mongo.Pipeline{projectStage} 106 107 // Specify the Collation option to set a default collation for the view. 108 opts := options.CreateView().SetCollation(&options.Collation{ 109 Locale: "en_US", 110 }) 111 112 if err := db.CreateView(context.TODO(), "usernames", "users", pipeline, opts); err != nil { 113 log.Fatal(err) 114 } 115} 116 117func ExampleDatabase_ListCollectionNames() { 118 var db *mongo.Database 119 120 // use a filter to only select capped collections 121 result, err := db.ListCollectionNames(context.TODO(), bson.D{{"options.capped", true}}) 122 if err != nil { 123 log.Fatal(err) 124 } 125 126 for _, coll := range result { 127 fmt.Println(coll) 128 } 129} 130 131func ExampleDatabase_RunCommand() { 132 var db *mongo.Database 133 134 // run an explain command to see the query plan for when a "find" is executed on collection "bar" 135 // specify the ReadPreference option to explicitly set the read preference to primary 136 findCmd := bson.D{{"find", "bar"}} 137 command := bson.D{{"explain", findCmd}} 138 opts := options.RunCmd().SetReadPreference(readpref.Primary()) 139 var result bson.M 140 if err := db.RunCommand(context.TODO(), command, opts).Decode(&result); err != nil { 141 log.Fatal(err) 142 } 143 fmt.Println(result) 144} 145 146func ExampleDatabase_Watch() { 147 var db *mongo.Database 148 149 // specify a pipeline that will only match "insert" events 150 // specify the MaxAwaitTimeOption to have each attempt wait two seconds for new documents 151 matchStage := bson.D{{"$match", bson.D{{"operationType", "insert"}}}} 152 opts := options.ChangeStream().SetMaxAwaitTime(2 * time.Second) 153 changeStream, err := db.Watch(context.TODO(), mongo.Pipeline{matchStage}, opts) 154 if err != nil { 155 log.Fatal(err) 156 } 157 158 // print out all change stream events in the order they're received 159 // see the mongo.ChangeStream documentation for more examples of using change streams 160 for changeStream.Next(context.TODO()) { 161 fmt.Println(changeStream.Current) 162 } 163} 164 165// Collection examples 166 167func ExampleCollection_Aggregate() { 168 var coll *mongo.Collection 169 170 // specify a pipeline that will return the number of times each name appears in the collection 171 // specify the MaxTime option to limit the amount of time the operation can run on the server 172 groupStage := bson.D{ 173 {"$group", bson.D{ 174 {"_id", "$name"}, 175 {"numTimes", bson.D{ 176 {"$sum", 1}, 177 }}, 178 }}, 179 } 180 opts := options.Aggregate().SetMaxTime(2 * time.Second) 181 cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{groupStage}, opts) 182 if err != nil { 183 log.Fatal(err) 184 } 185 186 // get a list of all returned documents and print them out 187 // see the mongo.Cursor documentation for more examples of using cursors 188 var results []bson.M 189 if err = cursor.All(context.TODO(), &results); err != nil { 190 log.Fatal(err) 191 } 192 for _, result := range results { 193 fmt.Printf("name %v appears %v times\n", result["_id"], result["numTimes"]) 194 } 195} 196 197func ExampleCollection_BulkWrite() { 198 var coll *mongo.Collection 199 var firstID, secondID primitive.ObjectID 200 201 // update the "email" field for two users 202 // for each update, specify the Upsert option to insert a new document if a document matching the filter isn't 203 // found 204 // set the Ordered option to false to allow both operations to happen even if one of them errors 205 firstUpdate := bson.D{{"$set", bson.D{{"email", "firstEmail@example.com"}}}} 206 secondUpdate := bson.D{{"$set", bson.D{{"email", "secondEmail@example.com"}}}} 207 models := []mongo.WriteModel{ 208 mongo.NewUpdateOneModel().SetFilter(bson.D{{"_id", firstID}}).SetUpdate(firstUpdate).SetUpsert(true), 209 mongo.NewUpdateOneModel().SetFilter(bson.D{{"_id", secondID}}).SetUpdate(secondUpdate).SetUpsert(true), 210 } 211 opts := options.BulkWrite().SetOrdered(false) 212 res, err := coll.BulkWrite(context.TODO(), models, opts) 213 if err != nil { 214 log.Fatal(err) 215 } 216 217 fmt.Printf("inserted %v and deleted %v documents\n", res.InsertedCount, res.DeletedCount) 218} 219 220func ExampleCollection_CountDocuments() { 221 var coll *mongo.Collection 222 223 // count the number of times the name "Bob" appears in the collection 224 // specify the MaxTime option to limit the amount of time the operation can run on the server 225 opts := options.Count().SetMaxTime(2 * time.Second) 226 count, err := coll.CountDocuments(context.TODO(), bson.D{{"name", "Bob"}}, opts) 227 if err != nil { 228 log.Fatal(err) 229 } 230 fmt.Printf("name Bob appears in %v documents", count) 231} 232 233func ExampleCollection_DeleteMany() { 234 var coll *mongo.Collection 235 236 // delete all documents in which the "name" field is "Bob" or "bob" 237 // specify the Collation option to provide a collation that will ignore case for string comparisons 238 opts := options.Delete().SetCollation(&options.Collation{ 239 Locale: "en_US", 240 Strength: 1, 241 CaseLevel: false, 242 }) 243 res, err := coll.DeleteMany(context.TODO(), bson.D{{"name", "bob"}}, opts) 244 if err != nil { 245 log.Fatal(err) 246 } 247 fmt.Printf("deleted %v documents\n", res.DeletedCount) 248} 249 250func ExampleCollection_DeleteOne() { 251 var coll *mongo.Collection 252 253 // delete at most one document in which the "name" field is "Bob" or "bob" 254 // specify the SetCollation option to provide a collation that will ignore case for string comparisons 255 opts := options.Delete().SetCollation(&options.Collation{ 256 Locale: "en_US", 257 Strength: 1, 258 CaseLevel: false, 259 }) 260 res, err := coll.DeleteOne(context.TODO(), bson.D{{"name", "bob"}}, opts) 261 if err != nil { 262 log.Fatal(err) 263 } 264 fmt.Printf("deleted %v documents\n", res.DeletedCount) 265} 266 267func ExampleCollection_Distinct() { 268 var coll *mongo.Collection 269 270 // find all unique values for the "name" field for documents in which the "age" field is greater than 25 271 // specify the MaxTime option to limit the amount of time the operation can run on the server 272 filter := bson.D{{"age", bson.D{{"$gt", 25}}}} 273 opts := options.Distinct().SetMaxTime(2 * time.Second) 274 values, err := coll.Distinct(context.TODO(), "name", filter, opts) 275 if err != nil { 276 log.Fatal(err) 277 } 278 279 for _, value := range values { 280 fmt.Println(value) 281 } 282} 283 284func ExampleCollection_EstimatedDocumentCount() { 285 var coll *mongo.Collection 286 287 // get and print an estimated of the number of documents in the collection 288 // specify the MaxTime option to limit the amount of time the operation can run on the server 289 opts := options.EstimatedDocumentCount().SetMaxTime(2 * time.Second) 290 count, err := coll.EstimatedDocumentCount(context.TODO(), opts) 291 if err != nil { 292 log.Fatal(err) 293 } 294 fmt.Printf("estimated document count: %v", count) 295} 296 297func ExampleCollection_Find() { 298 var coll *mongo.Collection 299 300 // find all documents in which the "name" field is "Bob" 301 // specify the Sort option to sort the returned documents by age in ascending order 302 opts := options.Find().SetSort(bson.D{{"age", 1}}) 303 cursor, err := coll.Find(context.TODO(), bson.D{{"name", "Bob"}}, opts) 304 if err != nil { 305 log.Fatal(err) 306 } 307 308 // get a list of all returned documents and print them out 309 // see the mongo.Cursor documentation for more examples of using cursors 310 var results []bson.M 311 if err = cursor.All(context.TODO(), &results); err != nil { 312 log.Fatal(err) 313 } 314 for _, result := range results { 315 fmt.Println(result) 316 } 317} 318 319func ExampleCollection_FindOne() { 320 var coll *mongo.Collection 321 var id primitive.ObjectID 322 323 // find the document for which the _id field matches id 324 // specify the Sort option to sort the documents by age 325 // the first document in the sorted order will be returned 326 opts := options.FindOne().SetSort(bson.D{{"age", 1}}) 327 var result bson.M 328 err := coll.FindOne(context.TODO(), bson.D{{"_id", id}}, opts).Decode(&result) 329 if err != nil { 330 // ErrNoDocuments means that the filter did not match any documents in the collection 331 if err == mongo.ErrNoDocuments { 332 return 333 } 334 log.Fatal(err) 335 } 336 fmt.Printf("found document %v", result) 337} 338 339func ExampleCollection_FindOneAndDelete() { 340 var coll *mongo.Collection 341 var id primitive.ObjectID 342 343 // find and delete the document for which the _id field matches id 344 // specify the Projection option to only include the name and age fields in the returned document 345 opts := options.FindOneAndDelete().SetProjection(bson.D{{"name", 1}, {"age", 1}}) 346 var deletedDocument bson.M 347 err := coll.FindOneAndDelete(context.TODO(), bson.D{{"_id", id}}, opts).Decode(&deletedDocument) 348 if err != nil { 349 // ErrNoDocuments means that the filter did not match any documents in the collection 350 if err == mongo.ErrNoDocuments { 351 return 352 } 353 log.Fatal(err) 354 } 355 fmt.Printf("deleted document %v", deletedDocument) 356} 357 358func ExampleCollection_FindOneAndReplace() { 359 var coll *mongo.Collection 360 var id primitive.ObjectID 361 362 // find the document for which the _id field matches id and add a field called "location" 363 // specify the Upsert option to insert a new document if a document matching the filter isn't found 364 opts := options.FindOneAndReplace().SetUpsert(true) 365 filter := bson.D{{"_id", id}} 366 replacement := bson.D{{"location", "NYC"}} 367 var replacedDocument bson.M 368 err := coll.FindOneAndReplace(context.TODO(), filter, replacement, opts).Decode(&replacedDocument) 369 if err != nil { 370 // ErrNoDocuments means that the filter did not match any documents in the collection 371 if err == mongo.ErrNoDocuments { 372 return 373 } 374 log.Fatal(err) 375 } 376 fmt.Printf("replaced document %v", replacedDocument) 377} 378 379func ExampleCollection_FindOneAndUpdate() { 380 var coll *mongo.Collection 381 var id primitive.ObjectID 382 383 // find the document for which the _id field matches id and set the email to "newemail@example.com" 384 // specify the Upsert option to insert a new document if a document matching the filter isn't found 385 opts := options.FindOneAndUpdate().SetUpsert(true) 386 filter := bson.D{{"_id", id}} 387 update := bson.D{{"$set", bson.D{{"email", "newemail@example.com"}}}} 388 var updatedDocument bson.M 389 err := coll.FindOneAndUpdate(context.TODO(), filter, update, opts).Decode(&updatedDocument) 390 if err != nil { 391 // ErrNoDocuments means that the filter did not match any documents in the collection 392 if err == mongo.ErrNoDocuments { 393 return 394 } 395 log.Fatal(err) 396 } 397 fmt.Printf("updated document %v", updatedDocument) 398} 399 400func ExampleCollection_InsertMany() { 401 var coll *mongo.Collection 402 403 // insert documents {name: "Alice"} and {name: "Bob"} 404 // set the Ordered option to false to allow both operations to happen even if one of them errors 405 docs := []interface{}{ 406 bson.D{{"name", "Alice"}}, 407 bson.D{{"name", "Bob"}}, 408 } 409 opts := options.InsertMany().SetOrdered(false) 410 res, err := coll.InsertMany(context.TODO(), docs, opts) 411 if err != nil { 412 log.Fatal(err) 413 } 414 fmt.Printf("inserted documents with IDs %v\n", res.InsertedIDs) 415} 416 417func ExampleCollection_InsertOne() { 418 var coll *mongo.Collection 419 420 // insert the document {name: "Alice"} 421 res, err := coll.InsertOne(context.TODO(), bson.D{{"name", "Alice"}}) 422 if err != nil { 423 log.Fatal(err) 424 } 425 fmt.Printf("inserted document with ID %v\n", res.InsertedID) 426} 427 428func ExampleCollection_ReplaceOne() { 429 var coll *mongo.Collection 430 var id primitive.ObjectID 431 432 // find the document for which the _id field matches id and add a field called "location" 433 // specify the Upsert option to insert a new document if a document matching the filter isn't found 434 opts := options.Replace().SetUpsert(true) 435 filter := bson.D{{"_id", id}} 436 replacement := bson.D{{"location", "NYC"}} 437 result, err := coll.ReplaceOne(context.TODO(), filter, replacement, opts) 438 if err != nil { 439 log.Fatal(err) 440 } 441 442 if result.MatchedCount != 0 { 443 fmt.Println("matched and replaced an existing document") 444 return 445 } 446 if result.UpsertedCount != 0 { 447 fmt.Printf("inserted a new document with ID %v\n", result.UpsertedID) 448 } 449} 450 451func ExampleCollection_UpdateMany() { 452 var coll *mongo.Collection 453 454 // increment the age for all users whose birthday is today 455 today := time.Now().Format("01-01-1970") 456 filter := bson.D{{"birthday", today}} 457 update := bson.D{{"$inc", bson.D{{"age", 1}}}} 458 459 result, err := coll.UpdateMany(context.TODO(), filter, update) 460 if err != nil { 461 log.Fatal(err) 462 } 463 464 if result.MatchedCount != 0 { 465 fmt.Println("matched and replaced an existing document") 466 return 467 } 468} 469 470func ExampleCollection_UpdateOne() { 471 var coll *mongo.Collection 472 var id primitive.ObjectID 473 474 // find the document for which the _id field matches id and set the email to "newemail@example.com" 475 // specify the Upsert option to insert a new document if a document matching the filter isn't found 476 opts := options.Update().SetUpsert(true) 477 filter := bson.D{{"_id", id}} 478 update := bson.D{{"$set", bson.D{{"email", "newemail@example.com"}}}} 479 480 result, err := coll.UpdateOne(context.TODO(), filter, update, opts) 481 if err != nil { 482 log.Fatal(err) 483 } 484 485 if result.MatchedCount != 0 { 486 fmt.Println("matched and replaced an existing document") 487 return 488 } 489 if result.UpsertedCount != 0 { 490 fmt.Printf("inserted a new document with ID %v\n", result.UpsertedID) 491 } 492} 493 494func ExampleCollection_Watch() { 495 var collection *mongo.Collection 496 497 // specify a pipeline that will only match "insert" events 498 // specify the MaxAwaitTimeOption to have each attempt wait two seconds for new documents 499 matchStage := bson.D{{"$match", bson.D{{"operationType", "insert"}}}} 500 opts := options.ChangeStream().SetMaxAwaitTime(2 * time.Second) 501 changeStream, err := collection.Watch(context.TODO(), mongo.Pipeline{matchStage}, opts) 502 if err != nil { 503 log.Fatal(err) 504 } 505 506 // print out all change stream events in the order they're received 507 // see the mongo.ChangeStream documentation for more examples of using change streams 508 for changeStream.Next(context.TODO()) { 509 fmt.Println(changeStream.Current) 510 } 511} 512 513// Session examples 514 515func ExampleWithSession() { 516 var client *mongo.Client // assume client is configured with write concern majority and read preference primary 517 518 // Specify the DefaultReadConcern option so any transactions started through the session will have read concern 519 // majority. 520 // The DefaultReadPreference and DefaultWriteConcern options aren't specified so they will be inheritied from client 521 // and be set to primary and majority, respectively. 522 opts := options.Session().SetDefaultReadConcern(readconcern.Majority()) 523 sess, err := client.StartSession(opts) 524 if err != nil { 525 log.Fatal(err) 526 } 527 defer sess.EndSession(context.TODO()) 528 529 // Call WithSession to start a transaction within the new session. 530 err = mongo.WithSession(context.TODO(), sess, func(sessCtx mongo.SessionContext) error { 531 // Use sessCtx as the Context parameter for InsertOne and FindOne so both operations are run under the new 532 // Session. 533 534 if err := sess.StartTransaction(); err != nil { 535 return err 536 } 537 538 coll := client.Database("db").Collection("coll") 539 res, err := coll.InsertOne(sessCtx, bson.D{{"x", 1}}) 540 if err != nil { 541 // Abort the transaction after an error. Use context.Background() to ensure that the abort can complete 542 // successfully even if the context passed to mongo.WithSession is changed to have a timeout. 543 _ = sess.AbortTransaction(context.Background()) 544 return err 545 } 546 547 var result bson.M 548 if err = coll.FindOne(sessCtx, bson.D{{"_id", res.InsertedID}}).Decode(result); err != nil { 549 // Abort the transaction after an error. Use context.Background() to ensure that the abort can complete 550 // successfully even if the context passed to mongo.WithSession is changed to have a timeout. 551 _ = sess.AbortTransaction(context.Background()) 552 return err 553 } 554 fmt.Println(result) 555 556 // Use context.Background() to ensure that the commit can complete successfully even if the context passed to 557 // mongo.WithSession is changed to have a timeout. 558 return sess.CommitTransaction(context.Background()) 559 }) 560} 561 562func ExampleClient_UseSessionWithOptions() { 563 var client *mongo.Client 564 565 // Specify the DefaultReadConcern option so any transactions started through the session will have read concern 566 // majority. 567 // The DefaultReadPreference and DefaultWriteConcern options aren't specified so they will be inheritied from client 568 // and be set to primary and majority, respectively. 569 opts := options.Session().SetDefaultReadConcern(readconcern.Majority()) 570 err := client.UseSessionWithOptions(context.TODO(), opts, func(sessCtx mongo.SessionContext) error { 571 // Use sessCtx as the Context parameter for InsertOne and FindOne so both operations are run under the new 572 // Session. 573 574 if err := sessCtx.StartTransaction(); err != nil { 575 return err 576 } 577 578 coll := client.Database("db").Collection("coll") 579 res, err := coll.InsertOne(sessCtx, bson.D{{"x", 1}}) 580 if err != nil { 581 // Abort the transaction after an error. Use context.Background() to ensure that the abort can complete 582 // successfully even if the context passed to mongo.WithSession is changed to have a timeout. 583 _ = sessCtx.AbortTransaction(context.Background()) 584 return err 585 } 586 587 var result bson.M 588 if err = coll.FindOne(sessCtx, bson.D{{"_id", res.InsertedID}}).Decode(result); err != nil { 589 // Abort the transaction after an error. Use context.Background() to ensure that the abort can complete 590 // successfully even if the context passed to mongo.WithSession is changed to have a timeout. 591 _ = sessCtx.AbortTransaction(context.Background()) 592 return err 593 } 594 fmt.Println(result) 595 596 // Use context.Background() to ensure that the commit can complete successfully even if the context passed to 597 // mongo.WithSession is changed to have a timeout. 598 return sessCtx.CommitTransaction(context.Background()) 599 }) 600 if err != nil { 601 log.Fatal(err) 602 } 603} 604 605func ExampleClient_StartSession_withTransaction() { 606 var client *mongo.Client // assume client is configured with write concern majority and read preference primary 607 608 // Specify the DefaultReadConcern option so any transactions started through the session will have read concern 609 // majority. 610 // The DefaultReadPreference and DefaultWriteConcern options aren't specified so they will be inheritied from client 611 // and be set to primary and majority, respectively. 612 opts := options.Session().SetDefaultReadConcern(readconcern.Majority()) 613 sess, err := client.StartSession(opts) 614 if err != nil { 615 log.Fatal(err) 616 } 617 defer sess.EndSession(context.TODO()) 618 619 // Specify the ReadPreference option to set the read preference to primary preferred for this transaction. 620 txnOpts := options.Transaction().SetReadPreference(readpref.PrimaryPreferred()) 621 result, err := sess.WithTransaction(context.TODO(), func(sessCtx mongo.SessionContext) (interface{}, error) { 622 // Use sessCtx as the Context parameter for InsertOne and FindOne so both operations are run in a 623 // transaction. 624 625 coll := client.Database("db").Collection("coll") 626 res, err := coll.InsertOne(sessCtx, bson.D{{"x", 1}}) 627 if err != nil { 628 return nil, err 629 } 630 631 var result bson.M 632 if err = coll.FindOne(sessCtx, bson.D{{"_id", res.InsertedID}}).Decode(result); err != nil { 633 return nil, err 634 } 635 return result, err 636 }, txnOpts) 637 if err != nil { 638 log.Fatal(err) 639 } 640 fmt.Printf("result: %v\n", result) 641} 642 643func ExampleNewSessionContext() { 644 var client *mongo.Client 645 646 // Create a new Session and SessionContext. 647 sess, err := client.StartSession() 648 if err != nil { 649 panic(err) 650 } 651 defer sess.EndSession(context.TODO()) 652 sessCtx := mongo.NewSessionContext(context.TODO(), sess) 653 654 // Start a transaction and sessCtx as the Context parameter to InsertOne and FindOne so both operations will be 655 // run in the transaction. 656 if err = sess.StartTransaction(); err != nil { 657 panic(err) 658 } 659 660 coll := client.Database("db").Collection("coll") 661 res, err := coll.InsertOne(sessCtx, bson.D{{"x", 1}}) 662 if err != nil { 663 // Abort the transaction after an error. Use context.Background() to ensure that the abort can complete 664 // successfully even if the context passed to NewSessionContext is changed to have a timeout. 665 _ = sess.AbortTransaction(context.Background()) 666 panic(err) 667 } 668 669 var result bson.M 670 if err = coll.FindOne(sessCtx, bson.D{{"_id", res.InsertedID}}).Decode(&result); err != nil { 671 // Abort the transaction after an error. Use context.Background() to ensure that the abort can complete 672 // successfully even if the context passed to NewSessionContext is changed to have a timeout. 673 _ = sess.AbortTransaction(context.Background()) 674 panic(err) 675 } 676 fmt.Printf("result: %v\n", result) 677 678 // Commit the transaction so the inserted document will be stored. Use context.Background() to ensure that the 679 // commit can complete successfully even if the context passed to NewSessionContext is changed to have a timeout. 680 if err = sess.CommitTransaction(context.Background()); err != nil { 681 panic(err) 682 } 683} 684 685// Cursor examples 686 687func ExampleCursor_All() { 688 var cursor *mongo.Cursor 689 690 var results []bson.M 691 if err := cursor.All(context.TODO(), &results); err != nil { 692 log.Fatal(err) 693 } 694 fmt.Println(results) 695} 696 697func ExampleCursor_Next() { 698 var cursor *mongo.Cursor 699 defer cursor.Close(context.TODO()) 700 701 // Iterate the cursor and print out each document until the cursor is exhausted or there is an error getting the 702 // next document. 703 for cursor.Next(context.TODO()) { 704 // A new result variable should be declared for each document. 705 var result bson.M 706 if err := cursor.Decode(&result); err != nil { 707 log.Fatal(err) 708 } 709 fmt.Println(result) 710 } 711 if err := cursor.Err(); err != nil { 712 log.Fatal(err) 713 } 714} 715 716func ExampleCursor_TryNext() { 717 var cursor *mongo.Cursor 718 defer cursor.Close(context.TODO()) 719 720 // Iterate the cursor and print out each document until the cursor is exhausted or there is an error getting the 721 // next document. 722 for { 723 if cursor.TryNext(context.TODO()) { 724 // A new result variable should be declared for each document. 725 var result bson.M 726 if err := cursor.Decode(&result); err != nil { 727 log.Fatal(err) 728 } 729 fmt.Println(result) 730 continue 731 } 732 733 // If TryNext returns false, the next document is not yet available, the cursor was exhausted and was closed, or 734 // an error occured. TryNext should only be called again for the empty batch case. 735 if err := cursor.Err(); err != nil { 736 log.Fatal(err) 737 } 738 if cursor.ID() == 0 { 739 break 740 } 741 } 742} 743 744func ExampleCursor_RemainingBatchLength() { 745 // Because we're using a tailable cursor, this must be a handle to a capped collection. 746 var coll *mongo.Collection 747 748 // Create a tailable await cursor. Specify the MaxAwaitTime option so requests to get more data will return if there 749 // are no documents available after two seconds. 750 findOpts := options.Find(). 751 SetCursorType(options.TailableAwait). 752 SetMaxAwaitTime(2 * time.Second) 753 cursor, err := coll.Find(context.TODO(), bson.D{}, findOpts) 754 if err != nil { 755 panic(err) 756 } 757 758 for { 759 // Iterate the cursor using TryNext. 760 if cursor.TryNext(context.TODO()) { 761 fmt.Println(cursor.Current) 762 } 763 764 // Handle cursor errors or the cursor being closed by the server. 765 if err = cursor.Err(); err != nil { 766 panic(err) 767 } 768 if cursor.ID() == 0 { 769 panic("cursor was unexpectedly closed by the server") 770 } 771 772 // Use the RemainingBatchLength function to rate-limit the number of network requests the driver does. If the 773 // current batch is empty, sleep for a short amount of time to let documents build up on the server before 774 // the next TryNext call, which will do a network request. 775 if cursor.RemainingBatchLength() == 0 { 776 time.Sleep(100 * time.Millisecond) 777 } 778 } 779} 780 781// ChangeStream examples 782 783func ExampleChangeStream_Next() { 784 var stream *mongo.ChangeStream 785 defer stream.Close(context.TODO()) 786 787 // Iterate the change stream and print out each event. 788 // Because the Next call blocks until an event is available, another way to iterate the change stream is to call 789 // Next in a goroutine and pass in a context that can be cancelled to abort the call. 790 791 for stream.Next(context.TODO()) { 792 // A new event variable should be declared for each event. 793 var event bson.M 794 if err := stream.Decode(&event); err != nil { 795 log.Fatal(err) 796 } 797 fmt.Println(event) 798 } 799 if err := stream.Err(); err != nil { 800 log.Fatal(err) 801 } 802} 803 804func ExampleChangeStream_TryNext() { 805 var stream *mongo.ChangeStream 806 defer stream.Close(context.TODO()) 807 808 // Iterate the change stream and print out each event until the change stream is closed by the server or there is an 809 // error getting the next event. 810 for { 811 if stream.TryNext(context.TODO()) { 812 // A new event variable should be declared for each event. 813 var event bson.M 814 if err := stream.Decode(&event); err != nil { 815 log.Fatal(err) 816 } 817 fmt.Println(event) 818 continue 819 } 820 821 // If TryNext returns false, the next change is not yet available, the change stream was closed by the server, 822 // or an error occurred. TryNext should only be called again for the empty batch case. 823 if err := stream.Err(); err != nil { 824 log.Fatal(err) 825 } 826 if stream.ID() == 0 { 827 break 828 } 829 } 830} 831 832func ExampleChangeStream_ResumeToken() { 833 var client *mongo.Client 834 var stream *mongo.ChangeStream // assume stream was created via client.Watch() 835 836 cancelCtx, cancel := context.WithCancel(context.TODO()) 837 defer cancel() 838 var wg sync.WaitGroup 839 wg.Add(1) 840 841 // Run a goroutine to process events. 842 go func() { 843 for stream.Next(cancelCtx) { 844 fmt.Println(stream.Current) 845 } 846 wg.Done() 847 }() 848 849 // Assume client needs to be disconnected. Cancel the context being used by the goroutine to abort any 850 // in-progres Next calls and wait for the goroutine to exit. 851 cancel() 852 wg.Wait() 853 854 // Before disconnecting the client, store the last seen resume token for the change stream. 855 resumeToken := stream.ResumeToken() 856 _ = client.Disconnect(context.TODO()) 857 858 // Once a new client is created, the change stream can be re-created. Specify resumeToken as the ResumeAfter option 859 // so only events that occurred after resumeToken will be returned. 860 var newClient *mongo.Client 861 opts := options.ChangeStream().SetResumeAfter(resumeToken) 862 newStream, err := newClient.Watch(context.TODO(), mongo.Pipeline{}, opts) 863 if err != nil { 864 log.Fatal(err) 865 } 866 defer newStream.Close(context.TODO()) 867} 868 869// IndexView examples 870 871func ExampleIndexView_CreateMany() { 872 var indexView *mongo.IndexView 873 874 // Create two indexes: {name: 1, email: 1} and {name: 1, age: 1} 875 // For the first index, specify no options. The name will be generated as "name_1_email_1" by the driver. 876 // For the second index, specify the Name option to explicitly set the name to "nameAge". 877 models := []mongo.IndexModel{ 878 { 879 Keys: bson.D{{"name", 1}, {"email", 1}}, 880 }, 881 { 882 Keys: bson.D{{"name", 1}, {"age", 1}}, 883 Options: options.Index().SetName("nameAge"), 884 }, 885 } 886 887 // Specify the MaxTime option to limit the amount of time the operation can run on the server 888 opts := options.CreateIndexes().SetMaxTime(2 * time.Second) 889 names, err := indexView.CreateMany(context.TODO(), models, opts) 890 if err != nil { 891 log.Fatal(err) 892 } 893 894 fmt.Printf("created indexes %v\n", names) 895} 896 897func ExampleIndexView_List() { 898 var indexView *mongo.IndexView 899 900 // Specify the MaxTime option to limit the amount of time the operation can run on the server 901 opts := options.ListIndexes().SetMaxTime(2 * time.Second) 902 cursor, err := indexView.List(context.TODO(), opts) 903 if err != nil { 904 log.Fatal(err) 905 } 906 907 // Get a slice of all indexes returned and print them out. 908 var results []bson.M 909 if err = cursor.All(context.TODO(), &results); err != nil { 910 log.Fatal(err) 911 } 912 fmt.Println(results) 913} 914