适用于 Azure Functions 2.x 及更高版本的 Azure Cosmos DB 输出绑定
Azure Cosmos DB 输出绑定允许使用 SQL API 将新文档写入 Azure Cosmos DB 数据库。
有关设置和配置详细信息,请参阅概述。
重要
本文使用选项卡来支持多个版本的 Node.js 编程模型。 v4 模型目前处于预览状态,旨在为 JavaScript 和 TypeScript 开发人员提供更为灵活和直观的体验。 在升级指南中详细了解 v3 和 v4 之间的差异。
Azure Functions 支持两种 Python 编程模型。 定义绑定的方式取决于选择的编程模型。
使用 Python v2 编程模型,可以直接在 Python 函数代码中使用修饰器定义绑定。 有关详细信息,请参阅 Python 开发人员指南。
本文同时支持两个编程模型。
可以使用以下 C# 模式之一创建 C# 函数:
- 进程内类库:编译的 C# 函数,该函数在与 Functions 运行时相同的进程中运行。
- 独立进程类库:编译的 C# 函数,该函数在独立于运行时的进程中运行。 支持在 .NET 5.0 上运行的 C# 函数需要独立的进程。
- C# 脚本:主要在 Azure 门户中创建 C# 函数时使用。
重要
对进程内模型的支持将于 2026 年 11 月 10 日结束。 为获得完全支持,强烈建议将应用迁移到独立工作模型。
示例
除非另有说明,否则本文中的示例针对的都是 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>
}
- 队列触发器,通过返回值将消息保存到数据库
- HTTP 触发器,通过返回值将文件保存到数据库
- HTTP 触发器,通过 OutputBinding 将一个文档保存到数据库
- HTTP 触发器,通过 OutputBinding 将多个文档保存到数据库
队列触发器,通过返回值将消息保存到数据库
以下示例展示了一个 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。 在此示例中,需要使用 @CosmosDBOutput
为 outputItem
参数提供注释,而不要使用函数签名。 使用 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。 在此示例中,需使用 @CosmosDBOutput
为 outputItem
参数提供注释,而不要使用函数签名。 输出参数 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,
});
要输出多个文档,请返回一个数组而不是单个对象。 例如:
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[]> {
// <displayInDocs>
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',
},
];
// </displayInDocs>
}
app.storageQueue('storageQueueTrigger1', {
queueName: 'inputqueue',
connection: 'MyStorageConnectionAppSetting',
return: output.cosmosDB({
databaseName: 'MyDatabase',
collectionName: 'MyCollection',
createIfNotExists: true,
connectionStringSetting: 'MyAccount_COSMOSDB',
}),
handler: storageQueueTrigger1,
});
以下示例显示了一个存储队列,该队列为接收以下格式的 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,
};
},
});
要输出多个文档,请返回一个数组而不是单个对象。 例如:
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) => {
// <displayInDocs>
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',
},
];
// </displayInDocs>
},
});
下面的示例演示如何使用输出绑定将数据写入 Azure Cosmos DB。 绑定在函数的配置文件 (functions.json) 中声明,并从队列消息中获取数据,然后写出到 Azure Cosmos DB 文档中。
{
"name": "EmployeeDocument",
"type": "cosmosDB",
"databaseName": "MyDatabase",
"collectionName": "MyCollection",
"createIfNotExists": true,
"connectionStringSetting": "MyStorageConnectionAppSetting",
"direction": "out"
}
在 run.ps1 文件中,从函数返回的对象将映射到 EmployeeDocument
对象,该对象将持久保存在数据库中。
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 属性 | 说明 |
---|---|
Connection | 应用设置或设置集合的名称,用于指定如何连接到受监视的 Azure Cosmos DB 帐户。 有关详细信息,请参阅连接。 |
DatabaseName | 带有受监视的容器的 Azure Cosmos DB 数据库的名称。 |
ContainerName | 要监视的容器的名称。 |
CreateIfNotExists | 一个用于指示是否创建容器(如果不存在)的布尔值。 默认值为 false,因为新容器是使用保留的吞吐量创建的,具有成本方面的隐含意义。 有关详细信息,请参阅定价页。 |
PartitionKey | 在 CreateIfNotExists 为 true 时,它定义所创建容器的分区键路径。 可以包含绑定参数。 |
ContainerThroughput | 在 CreateIfNotExists 为 true 时,它定义所创建容器的吞吐量。 |
PreferredLocations | (可选)为 Azure Cosmos DB 服务中的异地复制数据库帐户定义首选位置(区域)。 值应以逗号分隔。 例如,China North,China North,China North 。 |
修饰符
仅适用于 Python v2 编程模型。
对于使用修饰器定义的 Python v2 功能,支持 cosmos_db_output
上的以下属性:
properties | 说明 |
---|---|
arg_name |
函数代码中使用的变量名称,表示发生更改的文档列表。 |
database_name |
带有受监视的集合的 Azure Cosmos DB 数据库的名称。 |
collection_name |
受到监视的 Azure Cosmos DB 集合的名称。 |
create_if_not_exists |
一个布尔值,指示如果数据库和集合不存在,是否应创建它们。 |
connection_string_setting |
正在监视的 Azure Cosmos DB 的连接字符串。 |
对于使用 function.json 定义的 Python 函数,请参阅“配置”部分。
批注
在 Java 函数运行时库中,对写入 Azure Cosmos DB 的参数使用 @CosmosDBOutput
注释。 此注释支持以下属性:
配置
仅适用于 Python v1 编程模型。
下表解释了在 function.json 文件中设置的绑定配置属性,其中属性因扩展版本而异。
function.json 属性 | 说明 |
---|---|
连接 | 应用设置或设置集合的名称,用于指定如何连接到受监视的 Azure Cosmos DB 帐户。 有关详细信息,请参阅连接。 |
databaseName | 带有受监视的容器的 Azure Cosmos DB 数据库的名称。 |
containerName | 要监视的容器的名称。 |
createIfNotExists | 一个用于指示是否创建容器(如果不存在)的布尔值。 默认值为 false,因为新容器是使用保留的吞吐量创建的,具有成本方面的隐含意义。 有关详细信息,请参阅定价页。 |
partitionKey | 在 createIfNotExists 为 true 时,它定义所创建容器的分区键路径。 可以包含绑定参数。 |
containerThroughput | 在 createIfNotExists 为 true 时,它定义所创建容器的吞吐量。 |
preferredLocations | (可选)为 Azure Cosmos DB 服务中的异地复制数据库帐户定义首选位置(区域)。 值应以逗号分隔。 例如,China North,China North,China North 。 |
有关完整示例的信息,请参阅示例部分。
使用情况
默认情况下,当写入函数中的输出参数时,将在数据库中创建一个文档。 应通过在传递给输出参数的 JSON 对象中指定 id
属性来指定输出文档的文档 ID。
注意
如果指定现有文档的 ID,它会被新的输出文档覆盖。
Cosmos DB 输入绑定支持的参数类型取决于所用的 Functions 运行时版本、扩展包版本以及 C# 模态。
如果希望函数写入单个文档,Cosmos DB 输出绑定可以绑定到以下类型:
类型 | 说明 |
---|---|
JSON 可序列化类型 | 表示文档的 JSON 内容的对象。 函数尝试将普通的旧 CLR 对象 (POCO) 类型序列化为 JSON 数据。 |
如果希望函数写入多个文档,Cosmos DB 输出绑定可以绑定到以下类型:
类型 | 说明 |
---|---|
T[] ,其中 T 是 JSON 可序列化类型 |
包含多个事件的数组。 每个条目表示一个事件。 |
对于其他输出方案,请直接从 Microsoft.Azure.Cosmos 创建和使用类型。
连接
connectionStringSetting
/connection
和 leaseConnectionStringSetting
/leaseConnection
属性是对指定应用应该如何连接到 Azure Cosmos DB 的环境配置的引用。 这些属性可以指定:
- 包含连接字符串的应用程序设置的名称
- 多个应用程序设置的共享前缀的名称,共同定义基于标识的连接。 此选项仅适用于 4.x 或更高版本的扩展中的
connection
和leaseConnection
版本。
如果配置的值既是单个设置的完全匹配,也是其他设置的前缀匹配,则使用完全匹配。
连接字符串
数据库帐户的连接字符串应存储在应用程序设置中,其名称与绑定配置的 connection 属性指定的值匹配。
基于标识的连接
如果使用 4.x 或更高版本的扩展,则无需将连接字符串与机密一起使用,可以使应用使用 Azure Active Directory 标识。 为此,需要定义公共前缀下的设置,该前缀映射到触发器和绑定配置中的 connection 属性。
在此模式下,扩展需要以下属性:
属性 | 环境变量模板 | 说明 | 示例值 |
---|---|---|---|
帐户终结点 | <CONNECTION_NAME_PREFIX>__accountEndpoint |
Azure Cosmos DB 帐户终结点 URI。 | https://<数据库帐户名称>.documents.azure.cn:443/ |
可以设置其他属性来自定义连接。 请参阅基于标识的连接的通用属性。
在 Azure Functions 服务中托管时,基于标识的连接将使用托管标识。 默认情况下使用系统分配的标识,但可以使用 credential
和 clientID
属性来指定用户分配的标识。 请注意,不支持为用户分配的标识配置资源 ID。 在其他上下文(如本地开发)中运行时,将改用开发人员标识,尽管可以进行自定义。 请参阅使用基于标识的连接进行本地开发。
向标识授予权限
无论使用何种标识,都必须具有执行所需操作的权限。 需要使用内置角色或者提供这些权限的自定义角色在 Azure RBAC 中分配角色。
重要
某些权限可能由并非所有上下文都需要的目标服务公开。 尽可能遵循最低权限原则,仅授予标识所需的权限。 例如,如果应用只需要从数据源进行读取即可,则使用仅具有读取权限的角色。 分配一个也具有该服务写入权限的角色并不恰当,因为对于读取操作来说,写入是多余的权限。 同样,你也希望确保角色分配的范围仅限于需要读取的资源。
你将需要创建一个角色分配,以便在运行时提供对数据库帐户的访问权限。 所有者等管理角色还不够。 下表显示了在正常操作中使用 Azure Cosmos DB 扩展时建议使用的内置角色。 根据所编写的代码,应用程序可能需要具有其他权限。
绑定类型 | 内置角色示例 |
---|---|
触发器 | Cosmos DB 内置数据参与者 |
输入绑定 | Cosmos DB 内置数据读取者 |
输出绑定 | Cosmos DB 内置数据参与者 |
异常和返回代码
绑定 | 参考 |
---|---|
Azure Cosmos DB | Azure Cosmos DB 的 HTTP 状态代码 |