你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Azure Cosmos DB for MongoDB vCore 生成 Go 控制台应用

本指南介绍如何生成 Go 控制台应用程序以连接到 Azure Cosmos DB for MongoDB vCore 群集。 设置您的开发环境,使用 Azure SDK for Go 中的 azidentity 包进行身份验证,并针对数据库中的文档执行常见操作。

先决条件

  • 现有的 Azure Cosmos DB for MongoDB (vCore) 群集。
  • 为群集配置了 Microsoft Entra 身份验证,已授予标识 dbOwner 角色。

  • 最新版本的 Go

配置控制台应用程序

接下来,创建新的控制台应用程序项目,并导入必要的库以向群集进行身份验证。

  1. 使用 go mod init 命令为项目创建新的 Go 模块。

    go mod init cosmicworks
    
  2. 请安装 azidentity 软件包以通过 Microsoft Entra ID 进行身份验证。

    go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity
    
  3. 安装 mongo 包以与 MongoDB vCore 群集交互。

    go get -u  go.mongodb.org/mongo-driver/v2/mongo
    
  4. 在项目目录中创建一 main.go 个名为的新文件。

    touch main.go
    

连接至群集

现在,使用 Azure.Identity 库获取一个 TokenCredential,以用于连接到您的群集。 官方 MongoDB 驱动程序具有一个特殊接口,必须实现该接口,以便从 Microsoft Entra 获取令牌,以便在连接到群集时使用。

  1. 首先,在main.go文件的顶部导入所需的包。

    import (
    	"context"
    	"crypto/tls"
    	"encoding/json"
    	"fmt"
    	"time"
    
    	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
    	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    
    	"go.mongodb.org/mongo-driver/v2/bson"
    	"go.mongodb.org/mongo-driver/v2/mongo"
    	"go.mongodb.org/mongo-driver/v2/mongo/options"
    )
    
  2. 创建在整个应用程序中使用的背景上下文。

     ctx := context.Background()
    
  3. 创建一个实例,该实例 DefaultAzureCredential 用于使用 Microsoft Entra ID 进行身份验证。

     credential, err := azidentity.NewDefaultAzureCredential(nil)
     if err != nil {
     	panic(err)
     }
    
  4. 创建在 MongoDB 驱动程序需要进行身份验证时获取访问令牌的回调函数。

     azureIdentityTokenCallback := func(_ context.Context,
     	_ *options.OIDCArgs) (*options.OIDCCredential, error) {
     	accessToken, err := credential.GetToken(ctx, policy.TokenRequestOptions{
     		Scopes: []string{"https://ossrdbms-aad.database.windows.net/.default"},
     	})
     	if err != nil {
     		return nil, err
     	}
     	return &options.OIDCCredential{
     		AccessToken: accessToken.Token,
     	}, nil
     }
    
  5. 设置群集名称并构造连接 URI。

     clusterName := "<azure-cosmos-db-mongodb-vcore-cluster-name>"
     uri := fmt.Sprintf("mongodb+srv://%s.global.mongocluster.cosmos.azure.com/", clusterName)
    
  6. 配置 MongoDB 客户端的身份验证凭据。

     auth := options.Credential{
     	AuthMechanism:       "MONGODB-OIDC",
     	OIDCMachineCallback: azureIdentityTokenCallback,
     }
    
  7. 使用连接参数、传输层安全性(TLS)配置和身份验证设置客户端选项。

     clientOptions := options.Client().
     	ApplyURI(uri).
     	SetConnectTimeout(2 * time.Minute).
     	SetRetryWrites(true).
     	SetTLSConfig(&tls.Config{}).
     	SetAuth(auth)
    
  8. 使用配置的选项创建 MongoDB 客户端实例。

     client, err := mongo.Connect(clientOptions)
     if err != nil {
     	panic(err)
     }
    
     fmt.Println("Client created")
    
  9. 添加一个 defer 语句,以确保应用程序退出时客户端正确断开连接。

     defer func() {
     	if err = client.Disconnect(ctx); err != nil {
     		panic(err)
     	}
     }()
    

执行常见操作

最后,使用官方库对数据库、集合和文档执行常见任务。 在这里,你将使用相同的类和方法与 MongoDB 或 DocumentDB 进行交互来管理集合和项。

  1. 按名称获取对数据库的引用。

     database := client.Database("<database-name>")
    
     fmt.Println("Database pointer created")
    
  2. 获取对数据库中集合的引用。

     collection := database.Collection("<collection-name>")
    
     fmt.Println("Collection pointer created")
    
  3. 定义产品结构来表示文档结构。

    type Product struct {
        ID        string `bson:"_id"`
        Category  string `bson:"category"`
        Name      string `bson:"name"`
        Quantity  int    `bson:"quantity"`
        Price     decimal128.Decimal128 `bson:"price"`
        Clearance bool   `bson:"clearance"`
    }
    
  4. 使用配置为collection.ReplaceOne操作来创建或更新文档。

     opts := options.Replace().SetUpsert(true)
     upsertFilter := bson.D{{Key: "_id", Value: "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb"}}
     priceDecimal, err := bson.ParseDecimal128("850.00")
     if err != nil {
     	panic(err)
     }
     document := Product{
     	ID:        "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
     	Category:  "gear-surf-surfboards",
     	Name:      "Yamba Surfboard",
     	Quantity:  12,
     	Price:     priceDecimal,
     	Clearance: false}
    
     result, err := collection.ReplaceOne(ctx, upsertFilter, document, opts)
     if err != nil {
     	panic(err)
     }
    
     fmt.Printf("Documents upserted count:\t%d\n", result.UpsertedCount)
    
  5. 使用 collection.FindOne 和带有 _idcategory 的筛选器阅读特定文档。

     readFilter := bson.D{{Key: "_id", Value: "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb"}, {Key: "category", Value: "gear-surf-surfboards"}}
     var target Product
     err = collection.FindOne(ctx, readFilter).Decode(&target)
     if err != nil {
     	panic(err)
     }
    
     fmt.Printf("Read document name:\t%s\n", target.Name)
    
  6. 查询多个与特定category匹配的文档,使用collection.Find

     queryFilter := bson.D{{Key: "category", Value: "gear-surf-surfboards"}}
     cursor, err := collection.Find(ctx, queryFilter)
     if err != nil {
     	panic(err)
     }
    
  7. 从游标中检索所有匹配的文档。

     var products []Product
     if err = cursor.All(ctx, &products); err != nil {
     	panic(err)
     }
    
  8. 遍历并显示查询中找到的所有产品。

     for _, product := range products {
     	json, err := json.Marshal(product)
     	if err != nil {
     		panic(err)
     	}
     	fmt.Printf("Found document:\t%s\n", string(json))
     }