...

Source file src/go.mongodb.org/mongo-driver/mongo/client_examples_test.go

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

     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  

View as plain text