【问题标题】:Cosmos SQL upsert not working as expectedCosmos SQL upsert 未按预期工作
【发布时间】:2019-08-11 08:02:18
【问题描述】:

如果我尝试使用已存在的 id 和分区键更新文档,如果容器上没有设置唯一约束,它会按预期工作。

但是,当我将表中的任何值设置为唯一时,则 upsert 不起作用并且我得到一个(409 冲突 - 一个 id 与文档的 id 字段匹配的文档已经存在)。在这种情况下,唯一约束不应该是一个问题,但它会导致这个错误,对于 upsert 有一个奇怪的错误描述,因为如果 id 已经存在则无关紧要。

我正在使用documentClient.upsertDocument(collectionLink, documentDefinition, null, true);

【问题讨论】:

  • 您的收藏是否已分区?您是否在每个 upsert 上发送相同的 id 和分区键值?
  • id 是通过在 upsertDocument 方法上设置 false 标志自动分配的。两个请求的分区键相同,两个请求的唯一字段相同。我希望更新插入相同的请求,因为我们有 2 个单独的云试图更新相同的请求。
  • 文档由其 Id 和分区键值唯一标识,与唯一字段配置无关。唯一字段可以添加额外的检查。如果您每次都发送带有随机“id”的 Upsert,那么 Upsert 将始终创建不同的文档。要让 Upsert 进行更新/替换,您需要提供文档的 id 作为请求的一部分,而不是自动生成的(这会使其每次都不同)。
  • 但它给我的例外是 id 是相同的。这只是使用具有匹配唯一值的随机生成的 id 的误导效果吗?
  • 所以你是对的,我需要自己定义 id 并为其他请求使用完全相同的 id。这与异常消息所说的完全相反,这是非常具有误导性的。请发布答案,我会将其标记为正确,谢谢!

标签: java azure-cosmosdb azure-cosmosdb-sqlapi


【解决方案1】:

Cosmos DB 的 Upsert / Replace 流程基于文档的唯一标识符(id 和 Partition Key 值),Unique Fields 用于为数据验证添加额外检查。

当进行Upsert操作时,服务会寻找一个已有的具有相同id和Partition Key值的文档,如果有则更新它,否则就创建它。

在您的情况下,您总是发送一个新的随机 id,因此 Upsert 没有找到要更新的现有文档,而是每次都创建一个新文档。

请在启动 Upsert 之前定义您自己的 id,并将 upsert 调用中的 autogenerate id 属性设置为其默认 (true) 值:client.upsertDocument(collectionLink, documentDefinition)

【讨论】:

  • 我需要插入一个新文档,当它被赋予一个新的'id'但分区键与现有文档的分区键相同时。但是它给了我一个 DocumentClientException。为什么是这样?我不应该能够拥有多个具有相同分区键值的文档吗?
  • 是的,您可以拥有许多具有相同分区键值的文档,但在该分区键值中不能有相同的id。检查 DocumentClientException 以了解失败的原因。如果您还使用唯一键,则可能会在某些唯一键约束中产生冲突。
  • 谢谢,是的,它是导致冲突的单独唯一键。我发现文档客户端异常经常具有误导性,因为我似乎在几种不同的情况下说“id 已经存在”,而现在 id 存在不是问题。
猜你喜欢
  • 2023-02-25
  • 1970-01-01
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 2021-04-25
  • 2013-01-29
相关资源
最近更新 更多