azure CosmosDB SQL应用编程接口:通过部分更新删除要素匹配条件

bq3bfh9z  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(117)

当我已经知道文档id时,我试图在嵌套数组中删除匹配条件的特定元素。

{
  "id": "Tim",
  "city": "Seattle",
  "gifts": [
     {
        "recipient": "Andrew",
        "gift": "blanket"
     },
     {
        "recipient": "Deborah",
        "gift": "board game"
     },
     {
        "recipient": "Chris",
        "gift": "coffee maker"
     }
  ]
}

我想从"gifts"数组中删除收件人为"Andrew"的所有元素。一个幼稚的方法是拉文档,删除数组元素,然后设置新文档。但这让我很担心,因为它暴露了一个竞争条件,在拉文档和更新文档的过程中,可能会对该数组进行不同的变异,而这些变异将丢失。
我想看看我是否可以执行部分文档更新来删除数组元素。但是,https://learn.microsoft.com/en-us/azure/cosmos-db/partial-document-update的部分文档更新文档声明(表示"删除"):
如果目标路径是数组索引,则将删除该索引,并将指定索引上方的所有元素向左移动一个位置。
因此,通过部分文档更新删除数组元素的唯一方法似乎是通过其数组索引。但是,如果我拉取其数组索引,然后执行更新,则会出现类似的争用情况:如果数组在提取文档和执行部分文档更新之间发生了变化,会怎么样?
我看到对于部分文档更新,您可以执行"条件更新":
有条件更新:对于上述模式,还可以添加类似SQL的过滤器 predicate (例如,从c开始,其中c. taskNum = 3),以便在 predicate 中指定的前提条件不满足时操作失败。
我想知道这是否是我可以用来实现我的目标的东西。
本质上,我想我在寻找类似https://www.mongodb.com/docs/manual/reference/operator/update/pull/的东西,但在SQL API中。

5q4ezhmt

5q4ezhmt1#

数组在提取文档和执行部分文档更新之间发生变化
避免对同一文档进行并发更新的唯一方法是执行乐观并发。您需要首先读取当前文档,获取它的ETag,然后将其传递给CosmosItemRequestOptions函数以用于更新操作:

requestOptions.setIfMatchETag("etag from the read");

完整示例:https://github.com/Azure-Samples/azure-cosmos-java-sql-api-samples/blob/0ead4ca33dac72c223285e1db866c9dc06f5fb47/src/main/java/com/azure/cosmos/examples/documentcrud/async/DocumentCRUDQuickstartAsync.java#L366-L418
在这种情况下,如果发生了任何并发更新,您将得到一个带有状态代码412的失败,这意味着发生了并发更新,您需要重试操作(读取、获取新etag、找到要删除的新索引、执行更新)。

相关问题