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