Поделиться через


Создание консольного приложения Go с помощью Azure Cosmos DB для виртуального ядра MongoDB

В этом руководстве объясняется, как создать консольное приложение Go для подключения к кластеру виртуальных ядер Azure Cosmos DB для MongoDB. Вы настраиваете среду разработки, используете azidentity пакет из пакета Azure SDK для Go для проверки подлинности и выполняете общие операции с документами в базе данных.

Предпосылки

  • Последняя версия Azure CLI в Azure Cloud Shell.

    • Если вы предпочитаете локально запускать справочные команды CLI, войдите в Azure CLI с помощью az login команды.
  • Настроена проверка подлинности Microsoft Entra для кластера с ролью, предоставленной вашему идентификатору root.

  • Последняя версия Go.

Настройка консольного приложения

Затем создайте проект консольного приложения и импортируйте необходимые библиотеки для проверки подлинности в кластере.

  1. Создайте модуль Go для проекта с помощью go mod init команды.

    go mod init cosmicworks
    
  2. azidentity Установите пакет для обработки проверки подлинности с помощью идентификатора Microsoft Entra.

    go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity
    
  3. Установите пакет mongo для взаимодействия с кластером vCore MongoDB.

    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 для функции upsert.

     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, а также фильтра с _id и category.

     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))
     }