在 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"
的原因是什么?
这与并发或事务问题无关;这是关于唯一键约束(或缺乏唯一键约束)。默认情况下存在的唯一唯一约束是
/id
。
如果您添加
/type
作为唯一键约束,那么这将阻止多个文档具有 type = "type1"
。
请注意,此约束位于分区内(并且您没有提及分区键)。
此外,您还需要重新创建容器 - 很确定您无法在创建后添加唯一的键约束。
更多信息这里