如何以原子方式在 Cosmos DB 中插入或替换实体?

问题描述 投票:0回答:1

在 Cosmos DB 中,我有一个容器来存储一堆产品类型。所有产品类型都有唯一的

type
,我们可以使用
type
作为每个产品类型的唯一标识。

以下是产品类型的示例:

{
    "type": "type1",
    "introduction": "this is type 1",
    "size": 10
}

我有一个插入或替换产品类型的流程。这个过程应该是原子的和事务性的,这意味着当容器中没有带有

type = "type3"
的项目,并且多个进程尝试将
{ type": "type3", "introduction": "this is type 3" }
插入容器时,在所有进程完成后应该只有一个带有
type = "type3"
的项目。

所以我使用存储过程来执行此插入或替换逻辑:

function addOrUpdateEntity(entity) {
    var documentQuery = {
            'query': 'SELECT * FROM c where c.type = @param',
            'parameters': [{ 'name': '@param', 'value': entity.type }]
        };

    __.queryDocuments(__.getSelfLink(), documentQuery,
        function (err, items) {
            if (items.length === 0) {
                __.createDocument(__.getSelfLink(), entity, {}, function(err, item, options) {
                    if (err) { throw err; }
                })
            } else if (items.length === 1) {
                const oldEntity = items[0];
                const newEntity = Object.assign({}, oldEntity);
                newEntity.introduction = entity.introduction
                __.replaceDocument(oldEntity._self, newEntity, function (err) {
                    if (err) { throw err; }
                });
            }
        }
    );
}  

但是在并发进程运行场景下,我得到了两个重复的项目

type = "type3"

根据这个文档,存储过程的执行是事务性的,那么重复项都有

type = "type3"
的原因是什么?

stored-procedures azure-cosmosdb
1个回答
0
投票

这与并发或事务问题无关;这是关于唯一键约束(或缺乏唯一键约束)。默认情况下存在的唯一唯一约束是

/id

如果您添加

/type
作为唯一键约束,那么这将阻止多个文档具有
type = "type1"

请注意,此约束位于分区内(并且您没有提及分区键)。

此外,您还需要重新创建容器 - 很确定您无法在创建后添加唯一的键约束。

更多信息这里

© www.soinside.com 2019 - 2024. All rights reserved.