1 // Copyright (C) MongoDB, Inc. 2017-present. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 7 package mongo_test 8 9 import ( 10 "context" 11 "fmt" 12 "log" 13 14 "go.mongodb.org/mongo-driver/bson" 15 "go.mongodb.org/mongo-driver/mongo" 16 "go.mongodb.org/mongo-driver/mongo/options" 17 "go.mongodb.org/mongo-driver/mongo/readpref" 18 ) 19 20 func ExampleClient() { 21 // Create a Client and execute a ListDatabases operation. 22 23 client, err := mongo.Connect( 24 context.TODO(), 25 options.Client().ApplyURI("mongodb://localhost:27017")) 26 if err != nil { 27 log.Fatal(err) 28 } 29 defer func() { 30 if err = client.Disconnect(context.TODO()); err != nil { 31 log.Fatal(err) 32 } 33 }() 34 35 collection := client.Database("db").Collection("coll") 36 result, err := collection.InsertOne(context.TODO(), bson.D{{"x", 1}}) 37 if err != nil { 38 log.Fatal(err) 39 } 40 fmt.Printf("inserted ID: %v\n", result.InsertedID) 41 } 42 43 func ExampleConnect_ping() { 44 // Create a Client to a MongoDB server and use Ping to verify that the 45 // server is running. 46 47 clientOpts := options.Client().ApplyURI("mongodb://localhost:27017") 48 client, err := mongo.Connect(context.TODO(), clientOpts) 49 if err != nil { 50 log.Fatal(err) 51 } 52 defer func() { 53 if err = client.Disconnect(context.TODO()); err != nil { 54 log.Fatal(err) 55 } 56 }() 57 58 // Call Ping to verify that the deployment is up and the Client was 59 // configured successfully. As mentioned in the Ping documentation, this 60 // reduces application resiliency as the server may be temporarily 61 // unavailable when Ping is called. 62 if err = client.Ping(context.TODO(), readpref.Primary()); err != nil { 63 log.Fatal(err) 64 } 65 } 66 67 func ExampleConnect_replicaSet() { 68 // Create and connect a Client to a replica set deployment. 69 // Given this URI, the Go driver will first communicate with localhost:27017 70 // and use the response to discover any other members in the replica set. 71 // The URI in this example specifies multiple members of the replica set to 72 // increase resiliency as one of the members may be down when the 73 // application is started. 74 75 clientOpts := options.Client().ApplyURI( 76 "mongodb://localhost:27017,localhost:27018/?replicaSet=replset") 77 client, err := mongo.Connect(context.TODO(), clientOpts) 78 if err != nil { 79 log.Fatal(err) 80 } 81 _ = client 82 } 83 84 func ExampleConnect_sharded() { 85 // Create and connect a Client to a sharded deployment. 86 // The URI for a sharded deployment should specify the mongos servers that 87 // the application wants to send messages to. 88 89 clientOpts := options.Client().ApplyURI( 90 "mongodb://localhost:27017,localhost:27018") 91 client, err := mongo.Connect(context.TODO(), clientOpts) 92 if err != nil { 93 log.Fatal(err) 94 } 95 _ = client 96 } 97 98 func ExampleConnect_sRV() { 99 // Create and connect a Client using an SRV record. 100 // SRV records allow administrators to configure a single domain to return a 101 // list of host names. The driver will resolve SRV records prefixed with 102 // "_mongodb_tcp" and use the returned host names to build its view of the 103 // deployment. 104 // See https://www.mongodb.com/docs/manual/reference/connection-string/ for more 105 // information about SRV. Full support for SRV records with sharded clusters 106 // requires driver version 1.1.0 or higher. 107 108 clientOpts := options.Client().ApplyURI("mongodb+srv://mongodb.example.com") 109 client, err := mongo.Connect(context.TODO(), clientOpts) 110 if err != nil { 111 log.Fatal(err) 112 } 113 _ = client 114 } 115 116 func ExampleConnect_direct() { 117 // Create a direct connection to a host. The driver will send all requests 118 // to that host and will not automatically discover other hosts in the 119 // deployment. 120 121 clientOpts := options.Client().ApplyURI( 122 "mongodb://localhost:27017/?connect=direct") 123 client, err := mongo.Connect(context.TODO(), clientOpts) 124 if err != nil { 125 log.Fatal(err) 126 } 127 _ = client 128 } 129 130 func ExampleConnect_sCRAM() { 131 // Configure a Client with SCRAM authentication 132 // (https://www.mongodb.com/docs/manual/core/security-scram/). 133 // The default authentication database for SCRAM is "admin". This can be 134 // configured via the authSource query parameter in the URI or the 135 // AuthSource field in the options.Credential struct. SCRAM is the default 136 // auth mechanism so specifying a mechanism is not required. 137 138 // To configure auth via URI instead of a Credential, use 139 // "mongodb://user:password@localhost:27017". 140 credential := options.Credential{ 141 Username: "user", 142 Password: "password", 143 } 144 clientOpts := options.Client().ApplyURI("mongodb://localhost:27017"). 145 SetAuth(credential) 146 client, err := mongo.Connect(context.TODO(), clientOpts) 147 if err != nil { 148 log.Fatal(err) 149 } 150 _ = client 151 } 152 153 func ExampleConnect_x509() { 154 // Configure a Client with X509 authentication 155 // (https://www.mongodb.com/docs/manual/core/security-x.509/). 156 157 // X509 can be configured with different sets of options in the connection 158 // string: 159 // 1. tlsCAFile (or SslCertificateAuthorityFile): Path to the file with 160 // either a single or bundle of certificate authorities to be considered 161 // trusted when making a TLS connection. 162 // 2. tlsCertificateKeyFile (or SslClientCertificateKeyFile): Path to the 163 // client certificate file or the client private key file. In the case that 164 // both are needed, the files should be concatenated. 165 166 // The SetAuth client option should also be used. The username field is 167 // optional. If it is not specified, it will be extracted from the 168 // certificate key file. The AuthSource is required to be $external. 169 170 caFilePath := "path/to/cafile" 171 certificateKeyFilePath := "path/to/client-certificate" 172 173 // To configure auth via a URI instead of a Credential, append 174 // "&authMechanism=MONGODB-X509" to the URI. 175 uri := "mongodb://host:port/?tlsCAFile=%s&tlsCertificateKeyFile=%s" 176 uri = fmt.Sprintf(uri, caFilePath, certificateKeyFilePath) 177 credential := options.Credential{ 178 AuthMechanism: "MONGODB-X509", 179 } 180 clientOpts := options.Client().ApplyURI(uri).SetAuth(credential) 181 182 client, err := mongo.Connect(context.TODO(), clientOpts) 183 if err != nil { 184 log.Fatal(err) 185 } 186 _ = client 187 } 188 189 func ExampleConnect_pLAIN() { 190 // Configure a Client with LDAP authentication 191 // (https://www.mongodb.com/docs/manual/core/authentication-mechanisms-enterprise/#security-auth-ldap). 192 // MongoDB Enterprise supports proxy authentication through an LDAP service 193 // that can be used through the PLAIN authentication mechanism. 194 // This auth mechanism sends the password in plaintext and therefore should 195 // only be used with TLS connections. 196 197 // To configure auth via a URI instead of a Credential, use 198 // "mongodb://ldap-user:ldap-pwd@localhost:27017/?authMechanism=PLAIN". 199 credential := options.Credential{ 200 AuthMechanism: "PLAIN", 201 Username: "ldap-user", 202 Password: "ldap-pwd", 203 } 204 clientOpts := options.Client().ApplyURI("mongodb://localhost:27017"). 205 SetAuth(credential) 206 207 client, err := mongo.Connect(context.TODO(), clientOpts) 208 if err != nil { 209 log.Fatal(err) 210 } 211 _ = client 212 } 213 214 func ExampleConnect_kerberos() { 215 // Configure a Client with GSSAPI/SSPI authentication (https://www.mongodb.com/docs/manual/core/kerberos/). 216 // MongoDB Enterprise supports proxy authentication through a Kerberos 217 // service. Using Kerberos authentication requires the "gssapi" build tag 218 // and cgo support during compilation. The default service name for Kerberos 219 // is "mongodb". This can be configured via the AuthMechanismProperties 220 // field in the options.Credential struct or the authMechanismProperties URI 221 // parameter. 222 223 // For Linux, the libkrb5 library is required. 224 // Users can authenticate in one of two ways: 225 // 1. Use an explicit password. In this case, a password must be specified 226 // in the URI or the options.Credential struct and no further setup is 227 // required. 228 // 2. Store authentication keys in keytab files. To do this, the kinit 229 // binary should be used to initialize a credential cache for authenticating 230 // the user principal. In this example, the invocation would be 231 // "kinit drivers@KERBEROS.EXAMPLE.COM". 232 233 // To configure auth via a URI instead of a Credential, use 234 // "mongodb://drivers%40KERBEROS.EXAMPLE.COM@mongo-server.example.com:27017/?authMechanism=GSSAPI". 235 credential := options.Credential{ 236 AuthMechanism: "GSSAPI", 237 Username: "drivers@KERBEROS.EXAMPLE.COM", 238 } 239 uri := "mongo-server.example.com:27017" 240 clientOpts := options.Client().ApplyURI(uri).SetAuth(credential) 241 242 client, err := mongo.Connect(context.TODO(), clientOpts) 243 if err != nil { 244 log.Fatal(err) 245 } 246 _ = client 247 } 248 249 func ExampleConnect_aWS() { 250 // Configure a Client with authentication using the MONGODB-AWS 251 // authentication mechanism. Credentials for this mechanism can come from 252 // one of four sources: 253 // 254 // 1. AWS IAM credentials (an access key ID and a secret access key) 255 // 256 // 2. Temporary AWS IAM credentials 257 // (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html) 258 // obtained from an AWS Security Token Service (STS) Assume Role request 259 // (https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) 260 // 261 // 3. AWS Lambda environment variables 262 // (https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime) 263 // 264 // 4. Temporary AWS IAM credentials assigned to an EC2 instance or ECS task 265 // (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) 266 267 // The order in which the driver searches for credentials is: 268 // 269 // 1. Credentials passed through the URI 270 // 2. Environment variables 271 // 3. ECS endpoint if and only if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is 272 // set 273 // 4. EC2 endpoint 274 // 275 // The following examples set the appropriate credentials via the 276 // ClientOptions.SetAuth method. All of these credentials can be specified 277 // via the ClientOptions.ApplyURI method as well. If using ApplyURI, both 278 // the username and password must be URL encoded (see net.URL.QueryEscape()) 279 280 // AWS IAM Credentials 281 282 // Applications can authenticate using AWS IAM credentials by providing a 283 // valid access key ID and secret access key pair as the username and 284 // password, respectively. 285 var accessKeyID, secretAccessKey string 286 awsCredential := options.Credential{ 287 AuthMechanism: "MONGODB-AWS", 288 Username: accessKeyID, 289 Password: secretAccessKey, 290 } 291 awsIAMClient, err := mongo.Connect( 292 context.TODO(), 293 options.Client().SetAuth(awsCredential)) 294 if err != nil { 295 panic(err) 296 } 297 _ = awsIAMClient 298 299 // AssumeRole 300 301 // Applications can authenticate using temporary credentials returned from 302 // an assume role request. These temporary credentials consist of an access 303 // key ID, a secret access key, and a security token. 304 var sessionToken string 305 assumeRoleCredential := options.Credential{ 306 AuthMechanism: "MONGODB-AWS", 307 Username: accessKeyID, 308 Password: secretAccessKey, 309 AuthMechanismProperties: map[string]string{ 310 "AWS_SESSION_TOKEN": sessionToken, 311 }, 312 } 313 assumeRoleClient, err := mongo.Connect( 314 context.TODO(), 315 options.Client().SetAuth(assumeRoleCredential)) 316 if err != nil { 317 panic(err) 318 } 319 _ = assumeRoleClient 320 321 // AWS Lambda (Environment Variables) 322 323 // When the username and password are not provided and the MONGODB-AWS 324 // mechanism is set, the client will fallback to using the environment 325 // variables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN 326 // for the access key ID, secret access key, and session token, 327 // respectively. These environment variables must not be URL encoded. 328 329 // $ export AWS_ACCESS_KEY_ID=<accessKeyID> 330 // $ export AWS_SECRET_ACCESS_KEY=<secretAccessKey> 331 // $ export AWS_SESSION_TOKEN=<sessionToken> 332 envVariablesCredential := options.Credential{ 333 AuthMechanism: "MONGODB-AWS", 334 } 335 envVariablesClient, err := mongo.Connect( 336 context.TODO(), 337 options.Client().SetAuth(envVariablesCredential)) 338 if err != nil { 339 panic(err) 340 } 341 _ = envVariablesClient 342 343 // ECS Container or EC2 Instance 344 345 // Applications can authenticate from an ECS container or EC2 instance via 346 // temporary credentials assigned to the machine. If using an ECS container, 347 // the "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment variable must be 348 // set to a non-empty value. The driver will query the ECS or EC2 endpoint 349 // to obtain the relevant credentials. 350 ecCredential := options.Credential{ 351 AuthMechanism: "MONGODB-AWS", 352 } 353 ecClient, err := mongo.Connect( 354 context.TODO(), 355 options.Client().SetAuth(ecCredential)) 356 if err != nil { 357 panic(err) 358 } 359 _ = ecClient 360 } 361 362 func ExampleConnect_stableAPI() { 363 // Configure a Client with stable API. 364 // 365 // Stable API is a new feature in MongoDB 5.0 that allows user-selectable 366 // API versions, subsets of MongoDB server semantics, to be declared on a 367 // Client. During communication with a server, Clients with a declared API 368 // version will force that server to behave in a manner compatible with the 369 // API version. Declaring an API version on your Client can be used to 370 // ensure consistent responses from a server, providing long term API 371 // stability for an application. 372 // 373 // The declared API version is applied to all commands run through the 374 // Client, including those sent through the generic RunCommand helper. 375 // Specifying stable API options in the command document AND declaring 376 // an API version on the Client is not supported and will lead to undefined 377 // behavior. To run any command with a different API version or without 378 // declaring one, create a separate Client that declares the appropriate API 379 // version. 380 381 // ServerAPIOptions must be declared with an API version. ServerAPIVersion1 382 // is a constant equal to "1". 383 serverAPI := options.ServerAPI(options.ServerAPIVersion1) 384 serverAPIClient, err := mongo.Connect( 385 context.TODO(), 386 options.Client().SetServerAPIOptions(serverAPI)) 387 if err != nil { 388 panic(err) 389 } 390 _ = serverAPIClient 391 392 // ServerAPIOptions can be declared with a Strict option. Declaring a strict 393 // API version will cause the MongoDB server to reject all commands that are 394 // not part of the declared API version. This includes command options and 395 // aggregation pipeline stages. For example, the following Distinct call 396 // would fail because the distinct command is not part of API version 1: 397 serverAPIStrict := options.ServerAPI(options.ServerAPIVersion1). 398 SetStrict(true) 399 serverAPIStrictClient, err := mongo.Connect( 400 context.TODO(), 401 options.Client().SetServerAPIOptions(serverAPIStrict)) 402 if err != nil { 403 panic(err) 404 } 405 406 coll := serverAPIStrictClient.Database("db").Collection("coll") 407 // Fails with error: (APIStrictError) Provided apiStrict:true, but the 408 // command distinct is not in API Version 1 409 _, err = coll.Distinct(context.TODO(), "distinct", bson.D{}) 410 log.Println(err) 411 412 // ServerAPIOptions can be declared with a DeprecationErrors option. 413 // DeprecationErrors can be used to enable command failures when using 414 // functionality that is deprecated in the declared API version. Note that 415 // at the time of this writing, no deprecations in API version 1 exist. 416 serverAPIDeprecation := options.ServerAPI(options.ServerAPIVersion1). 417 SetDeprecationErrors(true) 418 serverAPIDeprecationClient, err := mongo.Connect( 419 context.TODO(), 420 options.Client().SetServerAPIOptions(serverAPIDeprecation)) 421 if err != nil { 422 panic(err) 423 } 424 _ = serverAPIDeprecationClient 425 } 426 427 func ExampleConnect_bSONOptions() { 428 // Configure a client that customizes the BSON marshal and unmarshal 429 // behavior. 430 431 // Specify BSON options that cause the driver to fallback to "json" 432 // struct tags if "bson" struct tags are missing, marshal nil Go maps as 433 // empty BSON documents, and marshals nil Go slices as empty BSON 434 // arrays. 435 bsonOpts := &options.BSONOptions{ 436 UseJSONStructTags: true, 437 NilMapAsEmpty: true, 438 NilSliceAsEmpty: true, 439 } 440 441 clientOpts := options.Client(). 442 ApplyURI("mongodb://localhost:27017"). 443 SetBSONOptions(bsonOpts) 444 445 client, err := mongo.Connect(context.TODO(), clientOpts) 446 if err != nil { 447 panic(err) 448 } 449 defer func() { 450 if err := client.Disconnect(context.TODO()); err != nil { 451 panic(err) 452 } 453 }() 454 455 coll := client.Database("db").Collection("coll") 456 457 // Define a struct that contains a map and a slice and uses "json" struct 458 // tags to specify field names. 459 type myDocument struct { 460 MyMap map[string]interface{} `json:"a"` 461 MySlice []string `json:"b"` 462 } 463 464 // Insert an instance of the struct with all empty fields. Expect the 465 // resulting BSON document to have a structure like {"a": {}, "b": []} 466 _, err = coll.InsertOne(context.TODO(), myDocument{}) 467 if err != nil { 468 panic(err) 469 } 470 } 471