You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Functions中Cosmos DB触发器如何获取新旧文档?

获取Cosmos DB触发器中的新旧文档版本

你遇到的这个问题很常见——默认的Cosmos DB触发器确实只提供更新后的文档实例。不过有两种可靠的方法可以让你同时获取新旧版本的文档,下面分别说明:

方案一:使用预触发器保存旧文档到辅助集合

这个方法的核心是利用Cosmos DB的预更新触发器,在文档被更新前自动把旧版本存到一个辅助集合里,之后你的Function就可以通过文档ID从这个集合中读取旧版本。

步骤1:创建辅助集合

先在你的Cosmos DB数据库里创建一个辅助集合(比如命名为ItemHistory),用来存储文档的历史版本。可以直接在Azure门户操作,或者用CLI/SDK创建。

步骤2:创建预更新触发器

在你的目标集合Items中创建一个预更新触发器,触发器类型选择Pre,操作选Update。触发器的JavaScript代码如下:

function preUpdate() {
    var context = getContext();
    var request = context.getRequest();
    var oldDocument = request.getBody(); // 获取更新前的旧文档
    var collection = context.getCollection();
    var collectionLink = collection.getSelfLink();

    // 把旧文档插入到辅助集合ItemHistory
    var createDocumentAccepted = collection.createDocument(
        collectionLink.replace("Items", "ItemHistory"),
        oldDocument,
        function(err) {
            if (err) throw new Error("Failed to save old document: " + err.message);
        }
    );

    if (!createDocumentAccepted) {
        throw new Error("Create document request was not accepted.");
    }
}

创建触发器后,记得在更新文档时指定触发这个触发器(如果是通过SDK操作,需要在请求中包含触发器名称)。

步骤3:修改Azure Function代码和绑定

首先,在你的函数绑定配置中添加一个Cosmos DB输入绑定,用来查询辅助集合中的旧文档:

{
  "bindings": [
    {
      "type": "cosmosDBTrigger",
      "name": "documents",
      "direction": "in",
      "leaseCollectionName": "leases",
      "connectionStringSetting": "AzureWebJobsCosmosDBConnectionString",
      "databaseName": "ToDoList",
      "collectionName": "Items",
      "createLeaseCollectionIfNotExists": true
    },
    {
      "type": "cosmosDB",
      "name": "oldDocument",
      "direction": "in",
      "databaseName": "ToDoList",
      "collectionName": "ItemHistory",
      "id": "{documents[0].id}",
      "connectionStringSetting": "AzureWebJobsCosmosDBConnectionString"
    }
  ],
  "disabled": false
}

然后修改你的Function代码,就可以同时拿到新旧文档了:

module.exports = async function (context, documents, oldDocument) {
    if (!!documents && documents.length > 0) {
        const newDoc = documents[0];
        context.log('Updated Document Id: ', newDoc.id);
        context.log('New Document: ', newDoc);
        context.log('Old Document: ', oldDocument);
        
        // 这里可以对比新旧文档的属性差异
    }
    context.done();
};

方案二:启用Cosmos DB版本保留并读取旧版本

如果你不想维护辅助集合,可以启用Cosmos DB容器的版本保留功能,这样Cosmos DB会自动保留文档的历史版本,你可以通过文档的版本ID或者时间戳来读取旧版本。

步骤1:启用版本保留

在Azure门户中找到你的Items集合,进入数据资源管理器,打开集合的设置,找到版本保留选项,设置保留期限(比如7天)并保存。也可以用Azure CLI命令启用:

az cosmosdb sql container update --account-name <your-account> --resource-group <your-rg> --database-name ToDoList --name Items --enable-versioning true --max-version-item-count 10

步骤2:在Function中读取旧版本

你需要在Function中使用Cosmos DB SDK来读取旧版本的文档,修改后的代码如下:

const { CosmosClient } = require("@azure/cosmos");

module.exports = async function (context, documents) {
    if (!!documents && documents.length > 0) {
        const newDoc = documents[0];
        context.log('Updated Document Id: ', newDoc.id);
        context.log('New Document: ', newDoc);

        // 初始化Cosmos客户端
        const client = new CosmosClient(process.env.AzureWebJobsCosmosDBConnectionString);
        const database = client.database("ToDoList");
        const container = database.container("Items");

        // 读取旧版本文档(这里读取上一个版本,你可以根据需要调整版本号)
        try {
            const oldDocResponse = await container.item(newDoc.id, newDoc._partitionKey).read({
                accessCondition: {
                    type: "IfNotModified",
                    condition: newDoc._etag // 使用新文档的ETag来获取旧版本
                },
                maxItemCount: -1,
                enableCrossPartitionQuery: true
            });
            context.log('Old Document: ', oldDocResponse.resource);
        } catch (err) {
            if (err.code === 412) {
                context.log('No older version found for document: ', newDoc.id);
            } else {
                context.error('Error fetching old document: ', err);
            }
        }
    }
    context.done();
};

注意:这种方式的旧版本有保留期限,超过期限后会被自动清理,适合不需要长期保留旧文档的场景。


内容的提问来源于stack exchange,提问作者Tushar patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:22:11