通过


你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure Cosmos DB Azure Functions 2.x 及更高版本的输出绑定

使用Azure Cosmos DB输出绑定,可以使用 SQL API 将新文档写入Azure Cosmos DB数据库。

有关设置和配置详细信息,请参阅概述

重要

本文使用选项卡来支持多个版本的 Node.js 编程模型。 v4 模型已正式发布,旨在为 JavaScript 和 TypeScript 开发人员提供更为灵活和直观的体验。 有关 v4 模型工作原理的更多详细信息,请参阅 Azure Functions Node.js 开发人员指南。 要详细了解 v3 和 v4 之间的差异,请参阅迁移指南

Azure Functions支持两个用于Python的编程模型。 定义绑定的方式取决于选择的编程模型。

Python v2 编程模型允许直接在Python函数代码中使用修饰器定义绑定。 有关详细信息,请参阅 Python 开发人员指南

本文同时支持两个编程模型。

可使用以下 C# 模式之一来创建 C# 函数:

  • 独立辅助角色模型:编译的 C# 函数,该函数在独立于运行时的工作进程中运行。 独立工作进程需要支持在 LTS 和非 LTS 版本上运行的 C# 函数,.NET和.NET框架。 独立工作进程函数的扩展使用 Microsoft.Azure.Functions.Worker.Extensions.* 命名空间。
  • 进程内模型:编译的 C# 函数,该函数在与 Functions 运行时相同的进程中运行。 在此模型的变体中,可以使用 C# 脚本运行 Functions,该脚本主要用于 C# 门户编辑。 进程内函数的扩展使用 Microsoft.Azure.WebJobs.Extensions.* 命名空间。

示例

除非另有说明,否则本文中的示例面向 Azure Cosmos DB 扩展 3.x 版。 若要与扩展版本 4.x 一起使用,需要将属性和属性名称中的字符串 collection 替换为 container,将 connection_string_setting 替换为 connection

以下代码定义了 MyDocument 类型:

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

    public string? Text { get; set; }

    public int Number { get; set; }

    public bool Boolean { get; set; }
}

在下面的示例中,返回类型是 IReadOnlyList<T>,它是来自触发器绑定参数的修改过的文档列表:

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

队列触发器,通过返回值将消息保存到数据库

以下示例演示一个Java函数,该函数使用队列存储中的消息中的数据向数据库添加文档。

@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 触发器,通过返回值将文件保存到数据库

以下示例显示了一个Java函数,其签名使用 @CosmosDBOutput 进行批注,并且其返回值类型为 String。 函数返回的 JSON 文档会自动写入相应的Azure Cosmos DB集合。

    @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 触发器,通过 OutputBinding 将一个文档保存到数据库

以下示例演示一个Java函数,该函数通过 OutputBinding<T> 输出参数将文档写入Azure Cosmos DB。 在此示例中,需要使用 outputItem@CosmosDBOutput 参数提供注释,而不要使用函数签名。 使用 OutputBinding<T>,函数可以利用绑定将文档写入Azure Cosmos DB,同时允许向函数调用方(如 JSON 或 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();
    }

HTTP 触发器,通过 OutputBinding 将多个文档保存到数据库

以下示例演示一个Java函数,该函数通过 OutputBinding<T> 输出参数将多个文档写入Azure Cosmos DB。 在此示例中,需使用 outputItem@CosmosDBOutput 参数提供注释,而不要使用函数签名。 输出参数 outputItem 有一个 ToDoItem 对象列表作为其模板参数类型。 使用 OutputBinding<T>,函数可以利用绑定将文档写入Azure Cosmos DB,同时允许向函数调用方(如 JSON 或 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();
    }

Java 函数运行时库中,对写入Azure Cosmos DB的参数使用 @CosmosDBOutput 注释。 批注参数类型应为 OutputBinding<T>,其中 T是本机Java类型或 POJO。

以下示例显示了一个存储队列,该队列为接收以下格式的 JSON 的队列触发了 TypeScript 函数

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

该函数为每个记录创建以下格式Azure Cosmos DB文档:

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

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

要输出多个文档,请返回一个数组而不是单个对象。 例如:

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

以下示例显示了一个存储队列,该队列为接收以下格式的 JSON 的队列触发了 JavaScript 函数

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

该函数为每个记录创建以下格式Azure Cosmos DB文档:

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

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

要输出多个文档,请返回一个数组而不是单个对象。 例如:

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

以下示例演示如何使用输出绑定将数据写入Azure Cosmos DB。 绑定在函数的配置文件(functions.json)中声明,并从队列消息中提取数据并将其写出到Azure Cosmos DB文档。

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

在 run.ps1 文件中,从函数返回的对象将映射到 对象,该对象将持久保存在数据库中。

param($QueueItem, $TriggerMetadata) 

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

以下示例演示如何将文档作为函数的输出写入Azure Cosmos DB数据库。 该示例取决于是使用 v1 还是 v2 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'

特性

进程内独立工作进程 C# 库使用特性来定义函数。 C# 脚本改用 function.json 配置文件,如 C# 脚本指南中所述。

Attribute 属性 说明
连接 应用设置或设置集合的名称,该集合指定如何连接到要监视的Azure Cosmos DB帐户。 有关详细信息,请参阅连接
数据库名称 Azure Cosmos DB 数据库的名称,其中包含要监视的容器。
ContainerName 要监视的容器的名称。
CreateIfNotExists 一个用于指示是否创建容器(如果不存在)的布尔值。 默认值为 false,因为新容器是使用保留的吞吐量创建的,具有成本方面的隐含意义。 有关详细信息,请参阅定价页
PartitionKey CreateIfNotExists 为 true 时,它定义所创建容器的分区键路径。 可以包含绑定参数。
ContainerThroughput CreateIfNotExists 为 true 时,它定义所创建容器的吞吐量
PreferredLocations (可选)为Azure Cosmos DB服务中的异地复制数据库帐户定义首选位置(区域)。 值应以逗号分隔。 例如,East US,South Central US,North Europe

修饰符

仅适用于 Python v2 编程 model.

对于使用修饰器定义的 Python v2 函数,cosmos_db_output上的以下属性:

properties 说明
arg_name 函数代码中使用的变量名称,表示发生更改的文档列表。
database_name Azure Cosmos DB 数据库的名称,其中包含要监视的容器。
container_name 要监视的Azure Cosmos DB容器的名称。
create_if_not_exists 一个布尔值,指示如果数据库和集合不存在,是否应创建它们。
connection_string_setting 正在监视的Azure Cosmos DB的连接字符串。

有关使用 function.json 定义的Python函数,请参阅 Configuration 部分。

批注

Java 函数运行时库中,对写入Azure Cosmos DB的参数使用 @CosmosDBOutput 注释。 此注释支持以下属性:

配置

仅适用于 Python v1 编程模型.

下表说明了可以在传递给方法“options”的对象“output.cosmosDB()”上设置的属性。 typedirectionname 属性不适用于 v4 模型。

下表解释了在 function.json 文件中设置的绑定配置属性,其中属性因扩展版本而异。

function.json 属性 说明
连接 应用设置或设置集合的名称,该集合指定如何连接到要监视的Azure Cosmos DB帐户。 有关详细信息,请参阅连接
databaseName Azure Cosmos DB 数据库的名称,其中包含要监视的容器。
containerName 要监视的容器的名称。
createIfNotExists 一个用于指示是否创建容器(如果不存在)的布尔值。 默认值为 false,因为新容器是使用保留的吞吐量创建的,具有成本方面的隐含意义。 有关详细信息,请参阅定价页
partitionKey createIfNotExists 为 true 时,它定义所创建容器的分区键路径。 可以包含绑定参数。
集装箱吞吐量 createIfNotExists 为 true 时,它定义所创建容器的吞吐量
preferredLocations (可选)为Azure Cosmos DB服务中的异地复制数据库帐户定义首选位置(区域)。 值应以逗号分隔。 例如,East US,South Central US,North Europe

有关完整示例的信息,请参阅示例部分

使用情况

默认情况下,当写入函数中的输出参数时,将在数据库中创建一个文档。 应通过在传递给输出参数的 JSON 对象中指定 id 属性来指定输出文档的文档 ID。

注意

如果指定现有文档的 ID,它会被新的输出文档覆盖。

输出函数参数必须定义为 func.Out[func.Document]。 有关详细信息,请参阅输出示例

Cosmos DB 输入绑定支持的参数类型取决于所用的 Functions 运行时版本、扩展包版本以及 C# 模态。

如果希望函数写入单个文档,Cosmos DB 输出绑定可以绑定到以下类型:

类型 说明
JSON 可序列化类型 表示文档的 JSON 内容的对象。 函数尝试将普通的旧 CLR 对象 (POCO) 类型序列化为 JSON 数据。

如果希望函数写入多个文档,Cosmos DB 输出绑定可以绑定到以下类型:

类型 说明
T[],其中 T 是 JSON 可序列化类型 包含多个事件的数组。 每个条目表示一个事件。

对于其他输出方案,请创建和使用 CosmosClientMicrosoft.Azure 中的其他类型。Cosmos直接。 有关使用依赖项注入从Azure SDK创建客户端类型的示例,请参阅 Register Azure 客户端

连接

connectionStringSetting / connectionleaseConnectionStringSetting/leaseConnection 属性引用环境配置,用于指定应用如何连接到Azure Cosmos DB。 它们可以指定:

  • 包含连接字符串的应用程序设置的名称。
  • 多个应用程序设置的共享前缀的名称,这些设置共同定义托管标识连接。 此选项仅适用于 connection中的 leaseConnection 版本。

如果配置的值既是单个设置的完全匹配,也是其他设置的前缀匹配,则使用完全匹配。

小窍门

建议通过连接字符串建立托管标识连接,以提高安全性。 连接字符串包括可公开的凭据,而托管标识无需管理机密。

如果使用的是 version 4.x 或更高版本的扩展 连接字符串,则可以让应用使用 Microsoft Entra 标识。 为此,请在映射到触发器和绑定配置中的连接属性的通用前缀下定义设置。

在此模式下,扩展需要以下应用程序设置:

基于模板的设置 说明 标识类型
<CONNECTION_NAME_PREFIX>__accountEndpoint Azure Cosmos DB帐户终结点 URI。 系统分配或用户分配
<CONNECTION_NAME_PREFIX>__credential 必须设置为 managedidentity 由用户指派
<CONNECTION_NAME_PREFIX>__clientId 用户分配的托管标识的客户端 ID。 由用户指派

替换为的值 <CONNECTION_NAME_PREFIX> 将绑定扩展视为连接设置的名称。

例如,如果绑定配置使用 connection = "CosmosDBConnection" 用户分配的托管标识指定,请配置以下应用程序设置:

{
    "CosmosDBConnection__accountEndpoint": "https://mycosmosdb.documents.azure.com:443/",
    "CosmosDBConnection__credential": "managedidentity",
    "CosmosDBConnection__clientId": "00000000-0000-0000-0000-000000000000"
}

小窍门

对生产方案使用用户分配的托管标识,需要对跨多个资源的标识权限进行精细控制。

可以使用模板中的其他设置进一步自定义连接。 请参阅基于标识的连接的通用属性

在Azure Functions服务中托管时,基于标识的连接使用 托管标识。 默认情况下使用系统分配的标识,但可以使用 credentialclientID 属性来指定用户分配的标识。 请注意,不支持为用户分配的标识配置资源 ID。 在其他上下文(如本地开发)中运行时,将改用开发人员标识,尽管可以进行自定义。 请参阅使用基于标识的连接进行本地开发

向标识授予权限

无论使用何种标识,都必须具有执行所需操作的权限。 对于大多数Azure服务,这意味着需要使用提供这些权限的内置角色或自定义角色在 Azure RBAC 中分配角色

重要

某些权限可能由并非所有上下文都需要的目标服务公开。 尽可能遵循最低权限原则,仅授予标识所需的权限。 例如,如果应用只需要从数据源进行读取即可,则使用仅具有读取权限的角色。 分配一个也具有该服务写入权限的角色并不恰当,因为对于读取操作来说,写入是多余的权限。 同样,你也希望确保角色分配的范围仅限于需要读取的资源。

Cosmos DB 不对数据操作使用 Azure RBAC。 而是使用基于类似概念构建的 Cosmos DB 内置 RBAC 系统。 你将需要创建一个角色分配,以便在运行时提供对数据库帐户的访问权限。 Azure RBAC 管理角色(如 Owner 是不够的。 下表显示了在正常操作中使用 Azure Cosmos DB 扩展时建议的内置角色。 根据所编写的代码,应用程序可能需要具有其他权限。

绑定类型 示例内置角色1
触发器2 Cosmos DB 内置数据参与者
输入绑定 Cosmos DB 内置数据读取者
输出绑定 Cosmos DB 内置数据参与者

1这些角色不能用于Azure RBAC 角色分配。 请参阅 Cosmos DB 内置 RBAC 系统文档,详细了解如何分配这些角色。

2 使用标识时,Cosmos DB 将容器创建视为管理操作。 它不可用作触发器的数据平面操作。 在设置函数之前,需确保创建触发器所需的容器(包括租用容器)。

异常和返回代码

绑定 参考
Azure Cosmos DB Azure Cosmos DB

后续步骤