Announcing the stable release of the Azure Cosmos DB client library for Go

Justine Cocchi

We’re excited to announce the stable release of the Azure Cosmos DB client library for Go, a native Go library that enables you to interact with Azure Cosmos DB for NoSQL accounts from your Go applications. The Azure Cosmos DB client library for Go provides an idiomatic API for you to perform operations on databases, containers, and items.

Learn how to use the Azure Cosmos DB client library for Go to build fast and scalable applications with Azure Cosmos DB. This release brings critical Azure Cosmos DB features for multi-region support and high availability to Go, such as the ability to set preferred regions and improved request diagnostics.

 

Install the package

The Azure Cosmos DB client library for Go is named azcosmos. To install the latest version, use the go get command.

go get -u github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos

Prerequisites for using the library include:

 

Creating a client

You need to have an Azure Cosmos DB for NoSQL account to create a client, which is the entry point for all operations on your account. If you have an Azure Subscription, you can use the Azure portal, Azure CLI, or Azure Resource Manager templates to create an account. If you don’t have an Azure Subscription you can create an Azure Cosmos DB for NoSQL free trial account or use the Azure Cosmos DB Emulator.

Once you have an account, you can use the NewCosmosClient function to create a client. The client should be created as a singleton, and it can interact with all databases and containers in your account.  You can authenticate using your account endpoint and either a TokenCredential, like DefaultAzureCredential, or you can use your account key. It’s recommended to use TokenCredential types for authentication and avoid password-based authentication.

 

DefaultAzureCredential combines several credential types into one for common production and development scenarios. It can authenticate using environment variables, managed identities, and more. To use Microsoft Entra identities to authenticate your data plane requests, configure Azure Cosmos DB data plane role-based access control. For more information about DefaultAzureCredential, see the azidentity documentation.

import (
	"github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos"
	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)

cred, err := azidentity.NewDefaultAzureCredential(nil)
handle(err)
client, err := azcosmos.NewClient("myAccountEndpointURL", cred, nil)
handle(err)

 

Use the Azure Cosmos DB account key

Azure Cosmos DB also supports authentication using account keys, which you can get from the Azure portal. Similarly, you can also authenticate using the account’s connection string.

const (
    cosmosDbEndpoint = "myAccountEndpointURL"
    cosmosDbKey = "myAccountKey"
)

cred, err := azcosmos.NewKeyCredential(cosmosDbKey)
handle(err)
client, err := azcosmos.NewClientWithKey(cosmosDbEndpoint, cred, nil)
handle(err)

 

Configure ClientOptions

Optionally, you can pass client configuration options using the ClientOptions struct. For accounts deployed in multiple regions, it’s recommended to configure preferred regions in the client options. The order of preferred regions guides the SDK on which region requests should be retried during an outage or transient failure. Configuring preferred regions is critical for high availability.

clientOptions := azcosmos.ClientOptions{
    PreferredRegions: []string{"West US", "East US"}
}
    
cred, err := azcosmos.NewKeyCredential(cosmosDbKey)
handle(err)
client, err := azcosmos.NewClientWithKey(cosmosDbEndpoint, cred, &clientOptions)
handle(err)

 

Creating a database

To create a database, you can use the CreateDatabase method of the client and pass a DatabaseProperties struct. Creating resources in the application isn’t supported when authenticating with Azure Cosmos DB role-based access control. It’s recommended to create resources outside of the flow of your application. The NewDatabase method returns a struct that represents an existing database and allows database level operations.

databaseProps := azcosmos.DatabaseProperties{ID: dbName}
response, err := client.CreateDatabase(context, databaseProps, nil)
handle(err)
database, err := client.NewDatabase(dbName)
handle(err)

 

Creating a container

To create a container, you can use the CreateContainer method of the database and pass a ContainerProperties struct. Similar to creating a database, creating containers isn’t recommended in the application flow and isn’t supported when authenticating with Azure Cosmos DB role-based access control. The NewContainer method returns a struct that represents an existing container and allows container level operations, including operations on items in the container.

containerProperties := azcosmos.ContainerProperties{
    ID: containerName,
    PartitionKeyDefinition: azcosmos.PartitionKeyDefinition{
        Paths: []string{"/myPartitionKeyPath"},
    },
}
    
throughput := azcosmos.NewManualThroughputProperties(400)
containerRes, err := database.CreateContainer(context, containerProperties, &azcosmos.CreateContainerOptions{
ThroughputProperties: &throughput
})
handle(err)
container, err := client.NewContainer(dbName, containerName)
handle(err)

 

Operations on items

Create an item

The CreateItem method of the container creates an item. You need to pass the partition key value of the item, the item to be created, and optionally, an ItemOptions struct. ItemOptions contains the request options, such as the consistency level and enabling content response on write. If you’re using session consistency, you should obtain the session token from your write operation. Pass the session token to your read operations to maintain the read-your-writes guarantee.

item := map[string]string{
    "id": "myDocId",
    "myPartitionKeyPath": "myPartitionKeyValue",
    "property": "value",
}
marshalledItem, err := json.Marshal(item)
handle(err)

pk := azcosmos.NewPartitionKeyString("myPartitionKeyValue")
itemResponse, err := container.CreateItem(context, pk, marshalledItem, nil)
handle(err)

itemSessionToken := itemResponse.SessionToken

 

Read an item

The ReadItem method of the container gets an item by its partition key and id. Like CreateItem, ReadItem also optionally takes the ItemOptions struct. When using session consistency, pass the session token from your write with each read request to maintain consistency.

id := "myDocId"
pk := azcosmos.NewPartitionKeyString("myPartitionKeyValue")
itemResponse, err = container.ReadItem(context, pk, id, &azcosmos.ItemOptions{SessionToken: itemSessionToken})
handle(err)
    
var itemResponseBody map[string]string
err = json.Unmarshal(itemResponse.Value, &itemResponseBody)
handle(err)

Inevitably, you will get an error response in your application at some point. One common scenario is attempting to read an item that doesn’t exist, which will return a 404 Not Found. You can inspect the status code of the error to decide how to handle it.

itemResponse, err = container.ReadItem(context, pk, id, &azcosmos.ItemOptions{SessionToken: itemSessionToken})
if err != nil {
    var responseErr *azcore.ResponseError
    errors.As(err, &responseErr)

    if responseErr.StatusCode != 404 {
        panic(responseErr)
    }
}

 

Query items

The NewQueryItemsPager method of the container performs a query over items in the container. Optionally, you can use QueryOptions to configure options for the request including setting query parameters and populating index metrics. Currently, queries must specify a partition key to execute against. You can see the request charge for each round trip of the query as part of the query response.

queryOptions := azcosmos.QueryOptions{
    QueryParameters: []azcosmos.QueryParameter{
        {"@property", "value"},
    },
}
pk := azcosmos.NewPartitionKeyString("myPartitionKeyValue")
query := "SELECT * FROM c WHERE c.property = @property",

queryPager := container.NewQueryItemsPager(query, pk, &queryOptions)
for queryPager.More() {
    queryResponse, err := queryPager.NextPage(context)
    handle(err)
    
    for _, item := range queryResponse.Items {
        var itemResponseBody map[string]interface{}
        json.Unmarshal(item, &itemResponseBody)
    }

    fmt.Printf("Query page received with %v items consuming %v RU", len(queryResponse.Items), queryResponse.RequestCharge)
}

 

Logging request diagnostics

All requests have associated diagnostics which are useful for debugging your application. The SDK uses the logging implementation from azcore to collect this information. To enable logging, set the environment variable AZURE_SDK_GO_LOGGING to all.

The SDK records logs for all types of events including requests, responses, and retries by default. They are output to stdout and printed directly to your console. You can configure a listener that acts differently, for example, writing logs to a file. If you apply log filtering based on event type, it’s recommended to keep logs from azlog.EventResponseError at a minimum.

import (
	"os"
	azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log"
)

f, err := os.Create("cosmos-log-file.txt")
handle(err)
defer f.Close()

// Configure the listener to write to a file rather than to the console
azlog.SetListener(func(event azlog.Event, s string) {
	f.WriteString(s + "\n")
})

 

Next steps

The Azure Cosmos DB client library for Go allows you to build and debug highly available applications built on Azure Cosmos DB. You can find more information and code samples in the API reference documentation, or follow the quick-start. Additionally, you can provide feedback and report issues on the GitHub issues page. We look forward to hearing from you and seeing what you build with Azure Cosmos DB and Go!

 

About Azure Cosmos DB

Azure Cosmos DB is a fully managed and serverless distributed database for modern app development, with SLA-backed speed and availability, automatic and instant scalability, and support for open-source PostgreSQL, MongoDB, and Apache Cassandra. Try Azure Cosmos DB for free here. To stay in the loop on Azure Cosmos DB updates, follow us on X, YouTube, and LinkedIn.

0 comments

Leave a comment

Feedback usabilla icon