IDocumentClient.UpsertDocumentAsync不会更新,它会插入重复的ID

Dev*_*nto 2 c# upsert azure azure-cosmosdb

我在C#中有一个VS2017解决方案,我正在使用IDocumentClient.UpsertDocumentAsync将一些文档嵌入到我的cosmosdb documentdb集合中.但是我注意到它实际上创建了具有相同id的新文档,而集合中已经存在具有该id的文档.

现在,在插入具有相同id的新文档之后,查询结果如下所示:

select * from c where c.id = "aaaa-bbbb-cccc"

[
    {
        "id": "aaaa-bbbb-cccc",
        "firstname": "john",
        "lastname": "doe"
    },
    {
        "id": "aaaa-bbbb-cccc",
        "firstname": "john",
        "lastname": "doe",
        "age": "35"
    }
]
Run Code Online (Sandbox Code Playgroud)

我对这种行为很困惑; 也许我没有正确理解"upsert"的定义.如果有人能为我澄清这一点,我将不胜感激.

Ara*_* R. 6

在Cosmos DB中,"id"不是唯一值.相反,它是分区键(在您的情况下为"age")和"id"的组合,它是唯一的.Cosmos DB允许分区键不存在(因为它对模式很宽松)并将缺少的分区键值视为特殊值(="undefined").分区键值也是不可变的 - 要更改这些值,您需要删除/插入.

所以在这种情况下,你有两个文件,一个用于upsert [age="35", "aaaa-bbbb-cccc"],另一个用[age=undefined, "aaaa-bbbb-cccc"]upsert调用创建.如果您将upsert调用更改为replace,则会收到NotFound错误.


Jay*_*ong 5

\n

我对这种行为很困惑;也许我没有正确理解“upsert”的定义。

\n
\n\n

UpsertAzure Cosmos DB 中的操作将创建一个文档(如果该文档尚不存在),否则将覆盖它。\xe2\x80\x9cShould I use a Create or a Replace operation?\xe2\x80\x9d,数据库会为您做出这个决定。这可以节省额外的请求单位费用,并且由于操作是原子的,因此消除了竞争条件的可能性。

\n\n

id然而,cosmos db 只是确保了per的唯一性partition key

\n\n

样本:

\n\n
[\n  {\n    "id": "1",\n    "name": "jay1"\n  },\n  {\n    "id": "1",\n    "name": "jay2"\n  },\n  {\n     "id": "1"\n  }\n]\n
Run Code Online (Sandbox Code Playgroud)\n\n

分区键name用于分片,它充当数据的逻辑分区,并为 Cosmos DB 提供跨分区分布数据的自然边界。以上3个文档有不同的分区:"jay1""jay2"、 ,None因此id属性在各自的逻辑分区中是唯一的。现在,如果您使用该Upsert方法将相同的文档添加id到各自的分区中,您将覆盖以前的文档。

\n\n

您可以参考文档:Azure Cosmos DB 中的唯一键Azure Cosmos DB 中的分区和缩放

\n