Enlace de salida de Azure Cosmos DB para Azure Functions 2.x y versiones superiores

El enlace de salida de Azure Cosmos DB permite escribir un nuevo documento en una base de datos de Azure Cosmos DB mediante SQL API.

Para obtener información sobre los detalles de instalación y configuración, vea la información general.

Importante

En este artículo se usan pestañas para admitir varias versiones del modelo de programación de Node.js. El modelo v4 está disponible de forma general y está diseñado para que los desarrolladores de JavaScript y TypeScript tengan una experiencia más flexible e intuitiva. Para más detalles acerca de cómo funciona el modelo v4, consulte la Guía para desarrolladores de Node.js de Azure Functions. Para más información sobre las diferencias entre v3 y v4, consulte la Guía de migración.

Azure Functions admite dos modelos de programación para Python. La forma en que defina los enlaces depende del modelo de programación seleccionado.

El modelo de programación de Python v2 permite definir enlaces mediante decoradores directamente en el código de función de Python. Para más información, consulte la Guía para desarrolladores de Python.

En este artículo se admiten los modelos de programación.

Se puede crear una función C# mediante uno de los siguientes modos de C#:

  • Modelo de trabajo aislado: función compilada en C# que se ejecuta en un proceso trabajador aislado del tiempo de ejecución. Se requiere un proceso de trabajo aislado para admitir funciones de C# ejecutándose en versiones de .NET que son y no son LTS y .NET Framework. Las extensiones para las funciones de proceso de trabajo aisladas usan espacios de nombres Microsoft.Azure.Functions.Worker.Extensions.*.
  • Modelo en curso: función C# compilada que se ejecuta en el mismo proceso que el tiempo de ejecución de Functions. En una variación de este modelo, Functions se puede ejecutar mediante el scripting de C#, que se admite principalmente para la edición del portal de C#. Las extensiones para funciones en proceso utilizan espacios de nombres Microsoft.Azure.WebJobs.Extensions.*.

Ejemplo

A menos que se indique lo contrario, los ejemplos de este artículo tienen como destino la versión 3.x de la extensión de Azure Cosmos DB. Para su uso con la versión 4.x de la extensión, debe reemplazar la cadena collection en los nombres de propiedad y atributo por container y connection_string_setting por connection.

En el código siguiente se define un 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; }
}

En el ejemplo siguiente, el tipo de valor devuelto es IReadOnlyList<T>, que es una lista modificada de documentos del parámetro de enlace de desencadenador:

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

Desencadenador de cola, guardar el mensaje en la base de datos mediante un valor devuelto

En el ejemplo siguiente se muestra una función de Java que agrega un documento a una base de datos con datos de un mensaje de 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 + " }";
   }

Desencadenador HTTP, guardar un documento en la base de datos mediante un valor devuelto

En el ejemplo siguiente se muestra una función de Java, cuya firma está anotada con @CosmosDBOutput y tiene un valor devuelto de tipo String. El documento JSON devuelto por la función se escribirá automáticamente en la colección de Azure Cosmos DB correspondiente.

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

Desencadenador HTTP, guardar un documento en la base de datos mediante OutputBinding

En el ejemplo siguiente se muestra una función de Java que escribe un documento en Azure Cosmos DB mediante un parámetro de salida OutputBinding<T>. En este ejemplo, el parámetro outputItem debe anotarse con @CosmosDBOutput, no con la firma de la función. El uso de OutputBinding<T> permite que la función aproveche el enlace para escribir el documento en Azure Cosmos DB, mientras que también permite devolver un valor diferente para el autor de llamada de la función, como un documento JSON o XML.

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

Desencadenador HTTP, guardar varios documentos en la base de datos mediante OutputBinding

En el ejemplo siguiente se muestra una función de Java que escribe varios documentos en Azure Cosmos DB mediante un parámetro de salida OutputBinding<T>. En este ejemplo, el parámetro outputItem se anota con @CosmosDBOutput, no con la firma de la función. El parámetro de salida, outputItem tiene una lista de objetos ToDoItem como su tipo de parámetro de plantilla. El uso de OutputBinding<T> permite que la función aproveche el enlace para escribir el documento en Azure Cosmos DB, mientras que también permite devolver un valor diferente para el autor de llamada de la función, como un documento JSON o XML.

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

En la biblioteca en tiempo de ejecución de funciones de Java, utilice la anotación @CosmosDBOutput en los parámetros que se van a escribir en Azure Cosmos DB. El tipo de parámetro de anotación debe ser OutputBinding<T>, donde T es un tipo nativo de Java o un POJO.

En el ejemplo siguiente se muestra una función de TypeScript desencadenada por una cola de almacenamiento para una cola que recibe JSON en el siguiente formato:

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

La función crea documentos de Azure Cosmos DB en el formato siguiente para cada registro:

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

Este es el 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 generar varios documentos, devuelva una matriz en lugar de un solo objeto. Por ejemplo:

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

En el ejemplo siguiente se muestra una función de JavaScript desencadenada por una cola de almacenamiento para una cola que recibe JSON en el siguiente formato:

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

La función crea documentos de Azure Cosmos DB en el formato siguiente para cada registro:

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

Este es el código de 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 generar varios documentos, devuelva una matriz en lugar de un solo objeto. Por ejemplo:

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

En el ejemplo siguiente se muestra cómo escribir datos en Azure Cosmos DB mediante un enlace de salida. El enlace se declara en el archivo de configuración de la función (functions.json), toma los datos de un mensaje de cola y escribe en un documento de Azure Cosmos DB.

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

En el archivo run.ps1, el objeto devuelto de la función se asigna a un objeto EmployeeDocument, que se conserva en la base de datos.

param($QueueItem, $TriggerMetadata) 

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

En el ejemplo siguiente se muestra cómo escribir un documento en una base de datos de Azure Cosmos DB como la salida de una función. El ejemplo depende de si usa el modelo de programación de Python v1 o v2.

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

Las bibliotecas de C# en proceso y de proceso de trabajo aislado usan atributos para definir la función. En su lugar, el script de C# usa un archivo de configuración function.json como se describe en la guía de scripting de C#.

Propiedad de atributo Descripción
Connection Nombre de una configuración de aplicación o colección de configuraciones que especifica cómo conectarse a la cuenta de Azure Cosmos DB que se va a supervisar. Para obtener más información, consulte Conexiones.
DatabaseName Nombre de la base de datos de Azure Cosmos DB con el contenedor que se está supervisando.
ContainerName Nombre del contenedor que se está supervisando.
CreateIfNotExists Valor booleano que indica si el contenedor se ha creado si no existía. El valor predeterminado es false porque los contenedores nuevos se crean con rendimiento reservado, lo que afecta al costo. Consulte la página de preciospara obtener más información.
PartitionKey Cuando el valor de CreateIfNotExists es true, define la ruta de la clave de partición para el contenedor creado. Puede incluir parámetros de enlace.
ContainerThroughput Cuando el valor de CreateIfNotExists es true, define el rendimiento del contenedor creado.
PreferredLocations (Opcional) Defina las ubicaciones preferidas (regiones) para las cuentas de base de datos con replicación geográfica en el servicio de Azure Cosmos DB. Los valores deben estar separados por comas. Por ejemplo, East US,South Central US,North Europe.

Elementos Decorator

Solo se aplica al modelo de programación de Python v2.

Para las funciones de Python v2 definidas mediante un decorador, se aplican las siguientes propiedades en cosmos_db_output:

Propiedad Descripción
arg_name Nombre de la variable que se utiliza en el código de función y que representa la lista de documentos con los cambios.
database_name Nombre de la base de datos de Azure Cosmos DB con la colección que se está supervisando.
collection_name Nombre de la colección de Azure Cosmos DB que se está supervisando.
create_if_not_exists Valor booleano que indica si se debe crear la base de datos y la colección si no existen.
connection_string_setting Cadena de conexión de Azure Cosmos DB que se está supervisando.

Para las funciones de Python definidas mediante function.json, consulte la sección Configuración.

anotaciones

En la biblioteca en tiempo de ejecución de funciones de Java, utilice la anotación @CosmosDBOutput en los parámetros que escriben en Azure Cosmos DB. La anotación admite las propiedades siguientes:

Configuración

Solo se aplica al modelo de programación de Python v1.

En la tabla siguiente se explican las propiedades que puede establecer en el objeto options que se pasa al métodooutput.cosmosDB(). Las propiedades type, direction y name no se aplican al modelo v4.

En la siguiente tabla se explican las propiedades de configuración de enlace que se definen en el archivo function.json, donde las propiedades difieren en la versión de la extensión:

Propiedad de function.json Descripción
connection Nombre de una configuración de aplicación o colección de configuraciones que especifica cómo conectarse a la cuenta de Azure Cosmos DB que se va a supervisar. Para obtener más información, consulte Conexiones.
databaseName Nombre de la base de datos de Azure Cosmos DB con el contenedor que se está supervisando.
containerName Nombre del contenedor que se está supervisando.
createIfNotExists Valor booleano que indica si el contenedor se ha creado si no existía. El valor predeterminado es false porque los contenedores nuevos se crean con rendimiento reservado, lo que afecta al costo. Consulte la página de preciospara obtener más información.
partitionKey Cuando el valor de createIfNotExists es true, define la ruta de la clave de partición para el contenedor creado. Puede incluir parámetros de enlace.
containerThroughput Cuando el valor de createIfNotExists es true, define el rendimiento del contenedor creado.
preferredLocations (Opcional) Defina las ubicaciones preferidas (regiones) para las cuentas de base de datos con replicación geográfica en el servicio de Azure Cosmos DB. Los valores deben estar separados por comas. Por ejemplo, East US,South Central US,North Europe.

Consulte la sección de ejemplos para ver ejemplos completos.

Uso

De forma predeterminada, cuando se escribe en el parámetro de salida de la función, se crea un documento en la base de datos. Puede precisar el identificador de documento del documento de salida si especifica la propiedad id en el objeto JSON pasado al parámetro de salida.

Nota:

Cuando especifica el identificador de un documento existente, se sobrescribe con el nuevo documento de salida.

El tipo de parámetro admitido por el enlace de salida de Cosmos DB depende de la versión del tiempo de ejecución de Functions, la versión del paquete de extensión y la modalidad de C# utilizada.

Cuando quiera que la función escriba en un único documento, el enlace de salida de Cosmos DB puede enlazarse a los siguientes tipos:

Tipo Descripción
Tipos serializables con JSON Un objeto que representa el contenido JSON de un documento. Functions intenta serializar un tipo de objetivo CLR (POCO) convencional en datos JSON.

Cuando quiera que la función escriba en varios documentos, el enlace de salida de Cosmos DB puede enlazarse a los siguientes tipos:

Tipo Descripción
T[] donde T es un tipo JSON serializable Una matriz que contiene varios documentos. Cada entrada representa un documento.

Para otros escenarios de salida, cree y use cosmosClient con otros tipos de Microsoft.Azure.Cosmos directamente. Consulte Registro de clientes de Azure para obtener un ejemplo de uso de la inserción de dependencias para crear un tipo de cliente a partir del SDK de Azure.

Conexiones

Las propiedades connectionStringSetting/connection y leaseConnectionStringSetting/leaseConnection son referencias a la configuración del entorno que especifica cómo se debe conectar la aplicación a Azure Cosmos DB. Pueden especificar:

Si el valor configurado es tanto una coincidencia exacta de una única configuración como una coincidencia de prefijo de otras configuraciones, se usa la coincidencia exacta.

Cadena de conexión

La cadena de conexión de la cuenta de base de datos debe almacenarse en una configuración de la aplicación con un nombre que coincida con el valor especificado por la propiedad de conexión de la configuración de enlace.

Conexiones basadas en identidades

Si usa la versión 4.x o posterior de la extensión, en lugar de usar una cadena de conexión con un secreto, puede hacer que la aplicación use una identidad de Microsoft Entra. Para ello, defina la configuración con un prefijo común que se asigne a la propiedad de conexión en la configuración de desencadenador y enlace.

En este modo, la extensión requiere las siguientes propiedades:

Propiedad Plantilla de variable de entorno Descripción Valor de ejemplo
Punto de conexión de la cuenta <CONNECTION_NAME_PREFIX>__accountEndpoint El identificador URI del punto de conexión de la cuenta de Azure Cosmos DB. https://<database_account_name>.documents.azure.com:443/

Se pueden establecer propiedades adicionales para personalizar la conexión. Consulte Propiedades comunes para conexiones basadas en identidades.

Cuando se hospeda en el servicio de Azure Functions, las conexiones basadas en identidades usan una identidad administrada. La identidad asignada por el sistema se usa de manera predeterminada, aunque se puede especificar una identidad asignada por el usuario con las propiedades credential y clientID. Tenga en cuenta que no se admite la configuración de una identidad asignada por el usuario con un identificador de recurso. Cuando se ejecuta en otros contextos, como el de desarrollo local, se usa en su lugar la identidad del desarrollador, aunque se puede personalizar. Consulte Desarrollo local con conexiones basadas en identidades.

Concesión de permiso a la identidad

Cualquier identidad que se utilice debe tener permisos para realizar las acciones previstas. Para la mayoría de los servicios de Azure, esto significa que debe asignar un rol en Azure RBAC mediante roles integrados o personalizados que proporcionen esos permisos.

Importante

Es posible que el servicio de destino muestre algunos permisos que no son necesarios para todos los contextos. Siempre que sea posible, respete el principio de privilegios mínimos y conceda solo los privilegios necesarios a la identidad. Por ejemplo, si la aplicación solo necesita poder leer desde un origen de datos, use un rol que solo tenga permiso de lectura. Sería inadecuado asignar un rol que también permita escribir en ese servicio, ya que sería un permiso excesivo para una operación de lectura. De forma similar, le interesa asegurarse de que la asignación de roles esté limitada solo a los recursos que se deben leer.

Cosmos DB no usa Azure RBAC para las operaciones de datos. En su lugar, usa un sistema de RBAC integrado de Cosmos DB que se basa en conceptos similares. Deberá crear una asignación de roles que proporcione acceso a la cuenta de base de datos en tiempo de ejecución. Los roles de administración de Azure RBAC, como Propietario, no son suficientes. En la tabla siguiente se muestran los roles integrados que se recomiendan al usar la extensión de Azure Cosmos DB en funcionamiento normal. Puede que la aplicación precise permisos adicionales en función del código que escriba.

Tipo de enlace Roles integrados de ejemplo1
Desencadenador2 Colaborador de datos integrado de Cosmos DB
Enlace de entrada Lector de datos integrado de Cosmos DB
Enlace de salida Colaborador de datos integrado de Cosmos DB

1 Estos roles no se pueden usar en una asignación de roles de RBAC de Azure. Consulte la documentación del sistema de RBAC integrado de Cosmos DB para más información sobre cómo asignar estos roles.

2 Cuando se usa la identidad, Cosmos DB trata la creación de contenedores como una operación de administración. No está disponible como una operación de plano de datos para el desencadenador. Deberá asegurarse de crear los contenedores necesarios para el desencadenador (incluido el contenedor de concesión) antes de configurar la función.

Excepciones y códigos de retorno

Enlace Referencia
Azure Cosmos DB Códigos de Estado HTTP en Azure Cosmos DB

Pasos siguientes