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

在CosmosDB中检查文档存在并按结果插入的最优实现方案是什么

问题解答

结论

完全可以通过Cosmos DB存储过程实现该需求,不仅能将原来的2次数据库请求压缩为1次,还能天然规避原实现中查询+插入两次请求间隙可能出现的并发竞态问题,因为Cosmos DB存储过程在单个逻辑分区内的所有操作是原子执行的。

前提约束

要保证跟踪表的分区键设置为OrderID:Cosmos DB存储过程的执行范围限定在单个逻辑分区内,同个OrderID的所有跟踪记录落在同一分区是存储过程能正确执行判断+插入逻辑的基础。

存储过程示例代码(服务端JS)

function insertTrackingIfNotExists(orderId) {
    const collection = getContext().getCollection();
    const collectionLink = collection.getSelfLink();
    const response = getContext().getResponse();

    // 1. 查询是否存在符合条件的已有记录
    const query = {
        query: "SELECT * FROM c WHERE c.OrderID = @orderId AND (c.Status = 'Completed' OR c.Status = 'InProgress')",
        parameters: [{name: "@orderId", value: orderId}]
    };

    const isAccepted = collection.queryDocuments(
        collectionLink,
        query,
        function (err, items) {
            if (err) throw err;

            // 已存在符合条件的记录,返回null
            if (items.length > 0) {
                response.setBody(null);
                return;
            }

            // 2. 不存在则新建跟踪记录
            const newTracking = {
                TrackingID: GUID(), // 服务端生成唯一ID,也可根据业务规则自定义生成逻辑
                OrderID: orderId,
                Status: "InProgress" // 可根据业务需要调整默认状态
            };

            collection.createDocument(collectionLink, newTracking, function (err, createdDoc) {
                if (err) throw err;
                // 返回新生成的TrackingID
                response.setBody(createdDoc.TrackingID);
            });
        }
    );

    if (!isAccepted) throw new Error("存储过程执行被拒绝,RU不足或请求过载");
}

客户端调用改造示例

public static async Task InsertTracking(string OrderID)
{
    // 调用存储过程,仅需1次请求,分区键指定为当前OrderID
    var result = await cosmosContainer.Scripts.ExecuteStoredProcedureAsync<string>(
        "insertTrackingIfNotExists", // 你创建存储过程时定义的ID
        new PartitionKey(OrderID), // 必须传入对应OrderID作为分区键
        new[] { OrderID } // 存储过程入参
    );

    string trackingID = result.Resource;
    if (trackingID != null)
    {
        NotifyNewTracking(trackingID);
    }
}

额外优势

相比原两次请求的实现,存储过程方案还解决了并发场景下的重复插入问题:原逻辑中两个请求同时查询到无记录,会同时触发插入导致重复数据,存储过程的原子执行特性完全避免了该问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 20:15:04