Редагувати

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


Azure Cosmos DB output binding for Azure Functions 2.x and higher

The Azure Cosmos DB output binding lets you write a new document to an Azure Cosmos DB database using the SQL API.

For information on setup and configuration details, see the overview.

Important

This article uses tabs to support multiple versions of the Node.js programming model. The v4 model is generally available and is designed to have a more flexible and intuitive experience for JavaScript and TypeScript developers. For more details about how the v4 model works, refer to the Azure Functions Node.js developer guide. To learn more about the differences between v3 and v4, refer to the migration guide.

Azure Functions supports two programming models for Python. The way that you define your bindings depends on your chosen programming model.

The Python v2 programming model lets you define bindings using decorators directly in your Python function code. For more information, see the Python developer guide.

This article supports both programming models.

A C# function can be created by using one of the following C# modes:

  • Isolated worker model: Compiled C# function that runs in a worker process that's isolated from the runtime. Isolated worker process is required to support C# functions running on LTS and non-LTS versions .NET and the .NET Framework. Extensions for isolated worker process functions use Microsoft.Azure.Functions.Worker.Extensions.* namespaces.
  • In-process model: Compiled C# function that runs in the same process as the Functions runtime. In a variation of this model, Functions can be run using C# scripting, which is supported primarily for C# portal editing. Extensions for in-process functions use Microsoft.Azure.WebJobs.Extensions.* namespaces.

Example

Unless otherwise noted, examples in this article target version 3.x of the Azure Cosmos DB extension. For use with extension version 4.x, you need to replace the string collection in property and attribute names with container and connection_string_setting with connection.

The following code defines a MyDocument type:

public class MyDocument
{
    public string Id { get; set; }

    public string Text { get; set; }

    public int Number { get; set; }

    public bool Boolean { get; set; }
}

In the following example, the return type is an IReadOnlyList<T>, which is a modified list of documents from trigger binding parameter:

using System.Collections.Generic;
using System.Linq;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public class CosmosDBFunction
    {
        private readonly ILogger<CosmosDBFunction> _logger;

        public CosmosDBFunction(ILogger<CosmosDBFunction> logger)
        {
            _logger = logger;
        }

        //<docsnippet_exponential_backoff_retry_example>
        [Function(nameof(CosmosDBFunction))]
        [ExponentialBackoffRetry(5, "00:00:04", "00:15:00")]
        [CosmosDBOutput("%CosmosDb%", "%CosmosContainerOut%", Connection = "CosmosDBConnection", CreateIfNotExists = true)]
        public object Run(
            [CosmosDBTrigger(
                "%CosmosDb%",
                "%CosmosContainerIn%",
                Connection = "CosmosDBConnection",
                LeaseContainerName = "leases",
                CreateLeaseContainerIfNotExists = true)] IReadOnlyList<MyDocument> input,
            FunctionContext context)
        {
            if (input != null && input.Any())
            {
                foreach (var doc in input)
                {
                    _logger.LogInformation("Doc Id: {id}", doc.Id);
                }

                // Cosmos Output
                return input.Select(p => new { id = p.Id });
            }

            return null;
        }
        //</docsnippet_exponential_backoff_retry_example>
    }

Queue trigger, save message to database via return value

The following example shows a Java function that adds a document to a database with data from a message in Queue storage.

@FunctionName("getItem")
@CosmosDBOutput(name = "database",
  databaseName = "ToDoList",
  collectionName = "Items",
  connectionStringSetting = "AzureCosmosDBConnection")
public String cosmosDbQueryById(
    @QueueTrigger(name = "msg",
      queueName = "myqueue-items",
      connection = "AzureWebJobsStorage")
    String message,
    final ExecutionContext context)  {
     return "{ id: \"" + System.currentTimeMillis() + "\", Description: " + message + " }";
   }

HTTP trigger, save one document to database via return value

The following example shows a Java function whose signature is annotated with @CosmosDBOutput and has return value of type String. The JSON document returned by the function will be automatically written to the corresponding Azure Cosmos DB collection.

    @FunctionName("WriteOneDoc")
    @CosmosDBOutput(name = "database",
      databaseName = "ToDoList",
      collectionName = "Items",
      connectionStringSetting = "Cosmos_DB_Connection_String")
    public String run(
            @HttpTrigger(name = "req",
              methods = {HttpMethod.GET, HttpMethod.POST},
              authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {

        // Item list
        context.getLogger().info("Parameters are: " + request.getQueryParameters());

        // Parse query parameter
        String query = request.getQueryParameters().get("desc");
        String name = request.getBody().orElse(query);

        // Generate random ID
        final int id = Math.abs(new Random().nextInt());

        // Generate document
        final String jsonDocument = "{\"id\":\"" + id + "\", " +
                                    "\"description\": \"" + name + "\"}";

        context.getLogger().info("Document to be saved: " + jsonDocument);

        return jsonDocument;
    }

HTTP trigger, save one document to database via OutputBinding

The following example shows a Java function that writes a document to Azure Cosmos DB via an OutputBinding<T> output parameter. In this example, the outputItem parameter needs to be annotated with @CosmosDBOutput, not the function signature. Using OutputBinding<T> lets your function take advantage of the binding to write the document to Azure Cosmos DB while also allowing returning a different value to the function caller, such as a JSON or XML document.

    @FunctionName("WriteOneDocOutputBinding")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req",
              methods = {HttpMethod.GET, HttpMethod.POST},
              authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
            @CosmosDBOutput(name = "database",
              databaseName = "ToDoList",
              collectionName = "Items",
              connectionStringSetting = "Cosmos_DB_Connection_String")
            OutputBinding<String> outputItem,
            final ExecutionContext context) {

        // Parse query parameter
        String query = request.getQueryParameters().get("desc");
        String name = request.getBody().orElse(query);

        // Item list
        context.getLogger().info("Parameters are: " + request.getQueryParameters());

        // Generate random ID
        final int id = Math.abs(new Random().nextInt());

        // Generate document
        final String jsonDocument = "{\"id\":\"" + id + "\", " +
                                    "\"description\": \"" + name + "\"}";

        context.getLogger().info("Document to be saved: " + jsonDocument);

        // Set outputItem's value to the JSON document to be saved
        outputItem.setValue(jsonDocument);

        // return a different document to the browser or calling client.
        return request.createResponseBuilder(HttpStatus.OK)
                      .body("Document created successfully.")
                      .build();
    }

HTTP trigger, save multiple documents to database via OutputBinding

The following example shows a Java function that writes multiple documents to Azure Cosmos DB via an OutputBinding<T> output parameter. In this example, the outputItem parameter is annotated with @CosmosDBOutput, not the function signature. The output parameter, outputItem has a list of ToDoItem objects as its template parameter type. Using OutputBinding<T> lets your function take advantage of the binding to write the documents to Azure Cosmos DB while also allowing returning a different value to the function caller, such as a JSON or XML document.

    @FunctionName("WriteMultipleDocsOutputBinding")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req",
              methods = {HttpMethod.GET, HttpMethod.POST},
              authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
            @CosmosDBOutput(name = "database",
              databaseName = "ToDoList",
              collectionName = "Items",
              connectionStringSetting = "Cosmos_DB_Connection_String")
            OutputBinding<List<ToDoItem>> outputItem,
            final ExecutionContext context) {

        // Parse query parameter
        String query = request.getQueryParameters().get("desc");
        String name = request.getBody().orElse(query);

        // Item list
        context.getLogger().info("Parameters are: " + request.getQueryParameters());

        // Generate documents
        List<ToDoItem> items = new ArrayList<>();

        for (int i = 0; i < 5; i ++) {
          // Generate random ID
          final int id = Math.abs(new Random().nextInt());

          // Create ToDoItem
          ToDoItem item = new ToDoItem(String.valueOf(id), name);

          items.add(item);
        }

        // Set outputItem's value to the list of POJOs to be saved
        outputItem.setValue(items);
        context.getLogger().info("Document to be saved: " + items);

        // return a different document to the browser or calling client.
        return request.createResponseBuilder(HttpStatus.OK)
                      .body("Documents created successfully.")
                      .build();
    }

In the Java functions runtime library, use the @CosmosDBOutput annotation on parameters that will be written to Azure Cosmos DB. The annotation parameter type should be OutputBinding<T>, where T is either a native Java type or a POJO.

The following example shows a storage queue triggered TypeScript function for a queue that receives JSON in the following format:

{
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

The function creates Azure Cosmos DB documents in the following format for each record:

{
    "id": "John Henry-123456",
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

Here's the TypeScript code:

import { app, InvocationContext, output } from '@azure/functions';

interface MyQueueItem {
    name: string;
    employeeId: string;
    address: string;
}

interface MyCosmosItem {
    id: string;
    name: string;
    employeeId: string;
    address: string;
}

export async function storageQueueTrigger1(queueItem: MyQueueItem, context: InvocationContext): Promise<MyCosmosItem> {
    return {
        id: `${queueItem.name}-${queueItem.employeeId}`,
        name: queueItem.name,
        employeeId: queueItem.employeeId,
        address: queueItem.address,
    };
}

app.storageQueue('storageQueueTrigger1', {
    queueName: 'inputqueue',
    connection: 'MyStorageConnectionAppSetting',
    return: output.cosmosDB({
        databaseName: 'MyDatabase',
        collectionName: 'MyCollection',
        createIfNotExists: true,
        connectionStringSetting: 'MyAccount_COSMOSDB',
    }),
    handler: storageQueueTrigger1,
});

To output multiple documents, return an array instead of a single object. For example:

return [
    {
        id: 'John Henry-123456',
        name: 'John Henry',
        employeeId: '123456',
        address: 'A town nearby',
    },
    {
        id: 'John Doe-123457',
        name: 'John Doe',
        employeeId: '123457',
        address: 'A town far away',
    },
];

The following example shows a storage queue triggered JavaScript function for a queue that receives JSON in the following format:

{
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

The function creates Azure Cosmos DB documents in the following format for each record:

{
    "id": "John Henry-123456",
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

Here's the JavaScript code:

const { app, output } = require('@azure/functions');

const cosmosOutput = output.cosmosDB({
    databaseName: 'MyDatabase',
    collectionName: 'MyCollection',
    createIfNotExists: true,
    connectionStringSetting: 'MyAccount_COSMOSDB',
});

app.storageQueue('storageQueueTrigger1', {
    queueName: 'inputqueue',
    connection: 'MyStorageConnectionAppSetting',
    return: cosmosOutput,
    handler: (queueItem, context) => {
        return {
            id: `${queueItem.name}-${queueItem.employeeId}`,
            name: queueItem.name,
            employeeId: queueItem.employeeId,
            address: queueItem.address,
        };
    },
});

To output multiple documents, return an array instead of a single object. For example:

return [
    {
        id: 'John Henry-123456',
        name: 'John Henry',
        employeeId: '123456',
        address: 'A town nearby',
    },
    {
        id: 'John Doe-123457',
        name: 'John Doe',
        employeeId: '123457',
        address: 'A town far away',
    },
];

The following example shows how to write data to Azure Cosmos DB using an output binding. The binding is declared in the function's configuration file (functions.json), and takes data from a queue message and writes out to an Azure Cosmos DB document.

{ 
  "name": "EmployeeDocument",
  "type": "cosmosDB",
  "databaseName": "MyDatabase",
  "collectionName": "MyCollection",
  "createIfNotExists": true,
  "connectionStringSetting": "MyStorageConnectionAppSetting",
  "direction": "out" 
} 

In the run.ps1 file, the object returned from the function is mapped to an EmployeeDocument object, which is persisted in the database.

param($QueueItem, $TriggerMetadata) 

Push-OutputBinding -Name EmployeeDocument -Value @{ 
    id = $QueueItem.name + '-' + $QueueItem.employeeId 
    name = $QueueItem.name 
    employeeId = $QueueItem.employeeId 
    address = $QueueItem.address 
} 

The following example demonstrates how to write a document to an Azure Cosmos DB database as the output of a function. The example depends on whether you use the v1 or v2 Python programming model.

import logging
import azure.functions as func

app = func.FunctionApp()

@app.route()
@app.cosmos_db_output(arg_name="documents", 
                      database_name="DB_NAME",
                      collection_name="COLLECTION_NAME",
                      create_if_not_exists=True,
                      connection_string_setting="CONNECTION_SETTING")
def main(req: func.HttpRequest, documents: func.Out[func.Document]) -> func.HttpResponse:
    request_body = req.get_body()
    documents.set(func.Document.from_json(request_body))
    return 'OK'

Attributes

Both in-process and isolated worker process C# libraries use attributes to define the function. C# script instead uses a function.json configuration file as described in the C# scripting guide.

Attribute property Description
Connection The name of an app setting or setting collection that specifies how to connect to the Azure Cosmos DB account being monitored. For more information, see Connections.
DatabaseName The name of the Azure Cosmos DB database with the container being monitored.
ContainerName The name of the container being monitored.
CreateIfNotExists A boolean value to indicate whether the container is created when it doesn't exist. The default is false because new containers are created with reserved throughput, which has cost implications. For more information, see the pricing page.
PartitionKey When CreateIfNotExists is true, it defines the partition key path for the created container. May include binding parameters.
ContainerThroughput When CreateIfNotExists is true, it defines the throughput of the created container.
PreferredLocations (Optional) Defines preferred locations (regions) for geo-replicated database accounts in the Azure Cosmos DB service. Values should be comma-separated. For example, East US,South Central US,North Europe.

Decorators

Applies only to the Python v2 programming model.

For Python v2 functions defined using a decorator, the following properties on the cosmos_db_output:

Property Description
arg_name The variable name used in function code that represents the list of documents with changes.
database_name The name of the Azure Cosmos DB database with the collection being monitored.
collection_name The name of the Azure Cosmos DB collection being monitored.
create_if_not_exists A Boolean value that indicates whether the database and collection should be created if they do not exist.
connection_string_setting The connection string of the Azure Cosmos DB being monitored.

For Python functions defined by using function.json, see the Configuration section.

Annotations

From the Java functions runtime library, use the @CosmosDBOutput annotation on parameters that write to Azure Cosmos DB. The annotation supports the following properties:

Configuration

Applies only to the Python v1 programming model.

The following table explains the properties that you can set on the options object passed to the output.cosmosDB() method. The type, direction, and name properties don't apply to the v4 model.

The following table explains the binding configuration properties that you set in the function.json file, where properties differ by extension version:

function.json property Description
connection The name of an app setting or setting collection that specifies how to connect to the Azure Cosmos DB account being monitored. For more information, see Connections.
databaseName The name of the Azure Cosmos DB database with the container being monitored.
containerName The name of the container being monitored.
createIfNotExists A boolean value to indicate whether the container is created when it doesn't exist. The default is false because new containers are created with reserved throughput, which has cost implications. For more information, see the pricing page.
partitionKey When createIfNotExists is true, it defines the partition key path for the created container. May include binding parameters.
containerThroughput When createIfNotExists is true, it defines the throughput of the created container.
preferredLocations (Optional) Defines preferred locations (regions) for geo-replicated database accounts in the Azure Cosmos DB service. Values should be comma-separated. For example, East US,South Central US,North Europe.

See the Example section for complete examples.

Usage

By default, when you write to the output parameter in your function, a document is created in your database. You should specify the document ID of the output document by specifying the id property in the JSON object passed to the output parameter.

Note

When you specify the ID of an existing document, it gets overwritten by the new output document.

The parameter type supported by the Cosmos DB output binding depends on the Functions runtime version, the extension package version, and the C# modality used.

When you want the function to write to a single document, the Cosmos DB output binding can bind to the following types:

Type Description
JSON serializable types An object representing the JSON content of a document. Functions attempts to serialize a plain-old CLR object (POCO) type into JSON data.

When you want the function to write to multiple documents, the Cosmos DB output binding can bind to the following types:

Type Description
T[] where T is JSON serializable type An array containing multiple documents. Each entry represents one document.

For other output scenarios, create and use a CosmosClient with other types from Microsoft.Azure.Cosmos directly. See Register Azure clients for an example of using dependency injection to create a client type from the Azure SDK.

Connections

The connectionStringSetting/connection and leaseConnectionStringSetting/leaseConnection properties are references to environment configuration which specifies how the app should connect to Azure Cosmos DB. They may specify:

If the configured value is both an exact match for a single setting and a prefix match for other settings, the exact match is used.

Connection string

The connection string for your database account should be stored in an application setting with a name matching the value specified by the connection property of the binding configuration.

Identity-based connections

If you are using version 4.x or higher of the extension, instead of using a connection string with a secret, you can have the app use an Microsoft Entra identity. To do this, you would define settings under a common prefix which maps to the connection property in the trigger and binding configuration.

In this mode, the extension requires the following properties:

Property Environment variable template Description Example value
Account Endpoint <CONNECTION_NAME_PREFIX>__accountEndpoint The Azure Cosmos DB account endpoint URI. https://<database_account_name>.documents.azure.com:443/

Additional properties may be set to customize the connection. See Common properties for identity-based connections.

When hosted in the Azure Functions service, identity-based connections use a managed identity. The system-assigned identity is used by default, although a user-assigned identity can be specified with the credential and clientID properties. Note that configuring a user-assigned identity with a resource ID is not supported. When run in other contexts, such as local development, your developer identity is used instead, although this can be customized. See Local development with identity-based connections.

Grant permission to the identity

Whatever identity is being used must have permissions to perform the intended actions. For most Azure services, this means you need to assign a role in Azure RBAC, using either built-in or custom roles which provide those permissions.

Important

Some permissions might be exposed by the target service that are not necessary for all contexts. Where possible, adhere to the principle of least privilege, granting the identity only required privileges. For example, if the app only needs to be able to read from a data source, use a role that only has permission to read. It would be inappropriate to assign a role that also allows writing to that service, as this would be excessive permission for a read operation. Similarly, you would want to ensure the role assignment is scoped only over the resources that need to be read.

Cosmos DB does not use Azure RBAC for data operations. Instead, it uses a Cosmos DB built-in RBAC system which is built on similar concepts. You will need to create a role assignment that provides access to your database account at runtime. Azure RBAC Management roles like Owner are not sufficient. The following table shows built-in roles that are recommended when using the Azure Cosmos DB extension in normal operation. Your application may require additional permissions based on the code you write.

Binding type Example built-in roles1
Trigger2 Cosmos DB Built-in Data Contributor
Input binding Cosmos DB Built-in Data Reader
Output binding Cosmos DB Built-in Data Contributor

1 These roles cannot be used in an Azure RBAC role assignment. See the Cosmos DB built-in RBAC system documentation for details on how to assign these roles.

2 When using identity, Cosmos DB treats container creation as a management operation. It is not available as a data-plane operation for the trigger. You will need to ensure that you create the containers needed by the trigger (including the lease container) before setting up your function.

Exceptions and return codes

Binding Reference
Azure Cosmos DB HTTP status codes for Azure Cosmos DB

Next steps