Compartir a través de

使用 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 身份验证,已授予标识 root 角色。

  • 最新版本的 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.chinacloudapi.cn/.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))
     }