Associação de saída do Azure Cosmos DB para o Azure Functions 2.x e superiores

Com a associação de saída do Azure Cosmos DB, você pode gravar um novo documento para um banco de dados do Azure Cosmos DB usando a API de SQL.

Para obter informações sobre a instalação e detalhes de configuração, confira a visão geral.

Importante

Este artigo usa guias para dar suporte a várias versões do modelo de programação Node.js. O modelo v4 normalmente está disponível e foi projetado para oferecer uma experiência mais flexível e intuitiva para desenvolvedores de JavaScript e TypeScript. Para obter mais detalhes sobre como funciona o modelo v4, consulte o Guia do desenvolvedor do Node.js para o Azure Functions. Para saber mais sobre as diferenças entre os modelos v3 e a v4, consulte o Guia de migração.

O Azure Functions dá suporte a dois modelos de programação para Python. A maneira como você define suas associações depende do modelo de programação escolhido.

O modelo de programação v2 do Python permite que você defina associações usando decoradores diretamente no código de função do Python. Para saber mais, confira o Guia do desenvolvedor do Python.

Este artigo dá suporte a ambos os modelos de programação.

A função C# pode ser criada por meio de um dos seguintes modos C#:

  • Modelo de trabalho isolado: função C# compilada executada em um processo de trabalho que está isolado do runtime. É necessário um processo de trabalho isolado para dar suporte às funções C# executadas nas versões LTS e não LTS do .NET e do .NET Framework. As extensões para funções do processo de trabalho isoladas usam namespaces Microsoft.Azure.Functions.Worker.Extensions.*.
  • Modelo em processo: função C# compilada no mesmo processo que o runtime do Functions. Em uma variação desse modelo, o Functions pode ser executado usando scripts C#, que é compatível principalmente com a edição do portal C#. As extensões para funções dentro do processo usam namespaces Microsoft.Azure.WebJobs.Extensions.*.

Exemplo

Salvo indicação em contrário, os exemplos neste artigo se referem à versão 3.x da extensão do Azure Cosmos DB. Para uso com a extensão versão 4.x, você precisa substituir a cadeia de caracteres collection nos nomes de propriedade e atributo por container e connection_string_setting com connection.

O código a seguir define um tipo MyDocument:

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

    public string Text { get; set; }

    public int Number { get; set; }

    public bool Boolean { get; set; }
}

No exemplo a seguir, o tipo de retorno é IReadOnlyList<T>, que é uma lista modificada de documentos do parâmetro de associação de gatilho:

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

Gatilho de fila, salva a mensagem ao banco de dados por meio do valor de retorno

O exemplo a seguir mostra uma função Java que adiciona um documento a um banco de dados com dados de uma mensagem no armazenamento de Filas.

@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 + " }";
   }

Gatilho HTTP, salva um documento ao banco de dados por meio do valor de retorno

O exemplo a seguir mostra uma função de Java cuja assinatura é anotada com @CosmosDBOutput e tem o valor retornado do tipo String. O documento JSON retornado pela função será gravado automaticamente à coleção do Azure Cosmos DB correspondente.

    @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;
    }

Gatilho HTTP, salva um documento ao banco de dados por meio do valor de OutputBinding

O exemplo a seguir mostra uma função de Java que grava um documento do Azure Cosmos DB por meio de um parâmetro de saída OutputBinding<T>. Neste exemplo, o parâmetro outputItem precisa ser anotado com @CosmosDBOutput, não a assinatura de função. Usar OutputBinding<T> permite que sua função tire proveito da associação para gravar o documento para Azure Cosmos DB, permitindo também retornar um valor diferente para o chamador da função, como um documento XML ou JSON.

    @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();
    }

Gatilho HTTP, salva vários documentos ao banco de dados por meio do valor de OutputBinding

O exemplo a seguir mostra uma função de Java que grava vários documentos do Azure Cosmos DB por meio de um parâmetro de saída OutputBinding<T>. Neste exemplo, o parâmetro outputItem precisa ser anotado com @CosmosDBOutput, não a assinatura de função. O parâmetro de saída outputItem tem uma lista de objetos ToDoItem como seu tipo de parâmetro de modelo. Usar OutputBinding<T> permite que sua função tire proveito da associação para gravar os documentos para o Azure Cosmos DB, permitindo também retornar um valor diferente para o chamador da função, como um documento XML ou JSON.

    @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();
    }

Na biblioteca de runtime de funções Java, use a anotação @CosmosDBOutput nos parâmetros que serão gravados no Azure Cosmos DB. O tipo de parâmetro de anotação deve ser OutputBinding<T>, em que T é um tipo Java nativo ou um POJO.

O exemplo a seguir mostra uma função TypeScript disparada por filas de armazenamento para uma fila que recebe JSON no seguinte formato:

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

A função cria documentos do Azure Cosmos DB no formato a seguir para cada registro:

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

Este é o código TypeScript:

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

Para gerar vários documentos, retorne uma matriz em vez de um único objeto. Por exemplo:

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',
    },
];

O exemplo a seguir mostra uma função JavaScript disparada por filas de armazenamento para uma fila que recebe JSON no seguinte formato:

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

A função cria documentos do Azure Cosmos DB no formato a seguir para cada registro:

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

Aqui está o código JavaScript:

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

Para gerar vários documentos, retorne uma matriz em vez de um único objeto. Por exemplo:

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',
    },
];

O seguinte exemplo mostra como gravar dados no Azure Cosmos DB usando uma associação de saída. A associação é declarada no arquivo de configuração da função (functions.json), e toma os dados de uma mensagem da fila e grava em um documento do Azure Cosmos DB.

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

No arquivo run.ps1, o objeto retornado da função é mapeado para um objeto EmployeeDocument, que é persistido no banco de dados.

param($QueueItem, $TriggerMetadata) 

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

O exemplo a seguir demonstra como gravar um documento em um banco de dados do Azure Cosmos DB como a saída de uma função. O exemplo depende se você usa o modelo de programação v1 ou v2 do Python.

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'

Atributos

As bibliotecas C# em processo e de processo de trabalho isolado usam atributos para definir a função. Em vez disso, o script C# usa um arquivo de configuração function.json, conforme descrito no guia de script C#.

Propriedade de atributo Descrição
Conexão O nome de uma configuração de aplicativo ou coleção de configurações que especifica como se conectar à conta do Azure Cosmos DB que está sendo monitorado. Para mais informações, consulte as Conexões.
DatabaseName O nome do banco de dados do Azure Cosmos DB com o contêiner que está sendo monitorado.
ContainerName O nome do contêiner que está sendo monitorado.
CreateIfNotExists É um valor booliano para indicar se o contêiner será criado caso não exista. O padrão é false, porque os contêineres são criados com a taxa de transferência reservada, o que tem implicações de preço. Para saber mais, confira a página de preço.
PartitionKey Quando CreateIfNotExists for true, ele definirá o caminho da chave de partição para o contêiner criado. Pode incluir parâmetros de associação.
ContainerThroughput Quando CreateIfNotExists for true, ele definirá a taxa de transferência do contêiner criado.
PreferredLocations (Opcional) Define locais (regiões) preferenciais para contas de banco de dados com replicação geográfica no serviço Azure Cosmos DB. Os valores devem ser separados por vírgulas. Por exemplo, East US,South Central US,North Europe.

Decoradores

Aplica-se somente ao modelo de programação v2 do Python.

Para funções do Python v2 definidas usando um decorador, as seguintes propriedades no cosmos_db_output:

Propriedade DESCRIÇÃO
arg_name O nome da variável usado no código de função que representa a lista de documentos com alterações.
database_name O nome do banco de dados do Azure Cosmos DB com a coleção que está sendo monitorada.
collection_name O nome da coleção do Azure Cosmos DB sendo monitorada.
create_if_not_exists Um valor Booliano que indica se o banco de dados e a coleção devem ser criados se eles não existirem.
connection_string_setting A cadeia de conexão do Azure Cosmos DB sendo monitorada.

Para funções do Python definidas usando function.json, confira a seção Configuração.

Anotações

Na biblioteca de runtime das funções Java, use a anotação @CosmosDBOutput nos parâmetros que gravam no Azure Cosmos DB. Essa anotação dá suporte às seguintes propriedades:

Configuração

Aplica-se apenas ao modelo de programação v1 do Python.

A tabela a seguir explica as propriedades que você pode definir no objeto options passado para o método output.cosmosDB(). As propriedades type, direction e name não se aplicam ao modelo v4.

A tabela a seguir explica as propriedades de configuração de associação que você define no arquivo function.json. Essas propriedades se diferenciam pela versão da extensão:

Propriedade function.json Descrição
connection O nome de uma configuração de aplicativo ou coleção de configurações que especifica como se conectar à conta do Azure Cosmos DB que está sendo monitorado. Para mais informações, consulte as Conexões.
databaseName O nome do banco de dados do Azure Cosmos DB com o contêiner que está sendo monitorado.
containerName O nome do contêiner que está sendo monitorado.
createIfNotExists É um valor booliano para indicar se o contêiner será criado caso não exista. O padrão é false, porque os contêineres são criados com a taxa de transferência reservada, o que tem implicações de preço. Para saber mais, confira a página de preço.
partitionKey Quando createIfNotExists for true, ele definirá o caminho da chave de partição para o contêiner criado. Pode incluir parâmetros de associação.
containerThroughput Quando createIfNotExists for true, ele definirá a taxa de transferência do contêiner criado.
preferredLocations (Opcional) Define locais (regiões) preferenciais para contas de banco de dados com replicação geográfica no serviço Azure Cosmos DB. Os valores devem ser separados por vírgulas. Por exemplo, East US,South Central US,North Europe.

Consulte a Seção de exemplo para obter exemplos completos.

Uso

Por padrão, quando você grava no parâmetro de saída em sua função, um documento é criado no banco de dados. Você deve especificar a ID do documento de saída especificando a propriedade id no objeto JSON passado para o parâmetro de saída.

Observação

Ao especificar a ID de um documento existente, ela é substituída pelo novo documento de saída.

Os tipos específicos com suporte pela associação de saída do Cosmos DB dependem da versão de runtime do Functions, da versão do pacote de extensão e da modalidade de C# usada.

Quando você desejar que a função seja gravada em um único documento, a associação de saída do Cosmos DB poderá ser associada aos seguintes tipos:

Type Descrição
Tipos serializáveis JSON Um objeto que representa o conteúdo JSON de um documento. O Functions tenta serializar um tipo de objeto CLR básico (POCO) em dados JSON.

Quando você desejar que a função seja gravada em vários documentos, a associação de saída do Cosmos DB poderá ser associada aos seguintes tipos:

Type Descrição
T[] em que T é um tipo serializável por JSON Uma matriz que contém vários documentos. Cada entrada representa um documento.

Para outros cenários de saída, crie e use um CosmosClient com outros tipos diretamente de Microsoft.Azure.Cosmos . Consulte Registrar clientes do Azure para obter um exemplo de como usar a injeção de dependência para criar um tipo de cliente do SDK do Azure.

conexões

As propriedades connectionStringSetting/connection e leaseConnectionStringSetting/leaseConnection são referências à configuração de ambiente que especifica como o aplicativo deve se conectar ao Azure Cosmos DB. Elas podem especificar:

  • O nome da configuração de um aplicativo contendo uma cadeia de conexão
  • O nome de um prefixo compartilhado com várias configurações de aplicativo, definindo juntas uma conexão baseada em identidade. Essa opção só está disponível para as versões connection e leaseConnection da connection.

Se o valor configurado for uma combinação exata para uma única configuração e um correspondência de prefixo para outras configurações, a correspondência exata será usada.

Cadeia de conexão

A cadeia de conexão para sua conta do banco de dados deve ser armazenada em uma configuração de aplicativo com um nome que corresponde ao valor especificado pela propriedade da conexão da configuração de associação.

Conexões baseadas em identidade

Se você estiver usando a versão 4.x ou superior da extensão, em vez de usar uma cadeia de conexão com um segredo, você pode fazer com que o aplicativo use uma identidade do Microsoft Entra. Para fazer isso, defina as configurações em um prefixo comum que mapeia para a propriedade da conexão na configuração de gatilho e de associação.

Nesse modo, a extensão exige as seguintes propriedades:

Propriedade Modelo de variável de ambiente Descrição Valor de exemplo
Ponto de extremidade da conta <CONNECTION_NAME_PREFIX>__accountEndpoint URI do ponto de extremidade da conta do Azure Cosmos DB. https://<nome_da_conta_do_banco_de_dados>.documents.azure.com:443/

É possível definir propriedades adicionais para personalizar a conexão. Confira Propriedades comuns para conexões baseadas em identidade.

Quando hospedadas no serviço de Azure Functions, as conexões baseadas em identidade usam uma identidade gerenciada. A identidade atribuída pelo sistema é usada por padrão, embora a identidade atribuída pelo usuário possa ser especificada com as propriedades credential e clientID. Observe que não há suporte para configurar uma identidade atribuída pelo usuário com uma ID de recurso. Quando executado em outros contextos, como desenvolvimento local, a identidade do desenvolvedor é usada, embora isso possa ser personalizado. Confira Desenvolvimento local com conexões baseadas em identidade.

Conceder permissão para a identidade

Qualquer identidade que esteja sendo usada deve ter permissões para executar as ações pretendidas. Para a maioria dos serviços do Azure, isso significa que será necessário atribuir uma função no Azure RBAC, usando as funções internas ou as personalizadas que fornecem essas permissões.

Importante

Algumas permissões que não são necessárias em todos os contextos podem ser expostas pelo serviço de destino. Sempre que possível, siga o princípio do privilégio mínimo, concedendo à identidade apenas os privilégios necessários. Por exemplo, se o aplicativo precisar apenas ser capaz de ler uma fonte de dados, use uma função que só tenha permissão de leitura. Seria inapropriado atribuir uma função que também permitisse a gravação nesse serviço, pois seria um excesso de permissões para uma operação de leitura. Da mesma forma, seria melhor garantir que a atribuição da função tivesse o escopo apenas sobre os recursos que precisam ser lidos.

O Cosmos DB não usa o RBAC do Azure para operações de dados. Em vez disso, ele usa um sistema RBAC interno do Cosmos DB que se baseia em conceitos semelhantes. Será necessário criar uma atribuição de função que forneça acesso a sua conta de banco de dados em runtime. As funções de Gerenciamento de RBAC do Azure, como a de Proprietário não são suficientes. A tabela a seguir mostra as funções internas recomendadas ao usar a extensão do Azure Cosmos DB em operação normal. Seu aplicativo pode exigir permissões adicionais com base no código escrito por você.

Tipo de associação Exemplo de funções internas1
Gatilho2 Colaborador de dados internos do Cosmos DB
Associação de entrada Leitor de dados internos do Cosmos DB
Associação de saída Colaborador de dados internos do Cosmos DB

1 Essas funções não podem ser usadas em uma atribuição de função RBAC do Azure. Confira a documentação do sistema RBAC interno do Cosmos DB para obter detalhes sobre como atribuir essas funções.

2 Ao usar a identidade, o Cosmos DB trata a criação de contêiner como uma operação de gerenciamento. Ele não está disponível como uma operação de plano de dados para o gatilho. Você precisará garantir a criação dos contêineres necessários para o gatilho (incluindo o contêiner de concessão) antes de configurar a função.

Exceções e códigos de retorno

Associação Referência
Azure Cosmos DB Códigos de status HTTP para Azure Cosmos DB

Próximas etapas