Cosmos DB Patch child object



我正在尝试使用新的部分文档更新功能修补Cosmos Db文档的子对象。然而,我找不到办法。

如果文档如下所示,您将如何将ID为2的ProductCode属性的子项(在Items数组中(更新为";A-111";使用新的Patch方法?


{
"id": "SalesOrder2",
"ponumber": "PO15428132599",
"OrderDate": "2005-07-01T00:00:00",
"DueDate": "2005-07-13T00:00:00",
"ShippedDate": "2005-07-08T00:00:00",
"AccountNumber": "Account2",
"SubTotal": 6107.082,
"TaxAmt": 586.1203,
"Freight": 183.1626,
"TotalDue": 4893.3929,
"DiscountAmt": 1982.872,
"Items": [
{
"Id": 1,
"OrderQty": 3,
"ProductCode": "A-123",
"ProductName": "Product 1",
"CurrencySymbol": "$",
"CurrencyCode": "USD",
"UnitPrice": 17.1,
"LineTotal": 5.7
},
{
"Id": 2,
"OrderQty": 2,
"ProductCode": "A-456",
"ProductName": "Product 2",
"CurrencySymbol": "$",
"CurrencyCode": "USD",
"UnitPrice": 10,
"LineTotal": 20
}
],
"_rid": "BsMkAMc43s4CAAAAAAAAAA==",
"_self": "dbs/BsMkAA==/colls/BsMkAMc43s4=/docs/BsMkAMc43s4CAAAAAAAAAA==/",
"_etag": ""00000000-0000-0000-e136-0dbec04601d7"",
"_attachments": "attachments/",
"_ts": 1637760030
}

您需要通过传递要更新的对象的特定索引来使用替换操作

在这种情况下,它将类似于

ItemResponse<SalesOrder> response = await container.PatchItemAsync<SalesOrder>(
id: "SalesOrder2",
partitionKey: new PartitionKey("/SalesOrder2"),
patchOperations: new[] { PatchOperation.Replace("/Items/1/ProductCode","A-111") });

不幸的是,没有办法使用类似sql的语法来使用条件更新特定的子数组项。你必须知道它的索引。这意味着你需要下拉你的文档(你只能选择你需要做这项工作的字段(。

这是冗长的,但一旦你通读了它,它真的不会做很多事情

文件:

{
"id": "15bab994-6ea2-436c-badd-a31f44d2e85d",
"conversationId": "5663d3ff-1347-4413-a584-9c634425c7ab",
"subject": "Office credit card",
"dateSent": "2022-06-08",
"dateCreated": "2022-06-06",
"isRetracted": false,
"parentId": "",
"isDeletedForSender": true,
"sender": {
"emailAddress": "nick@gmail.com",
"isUnread": true
},
"recipients": [
{
"id": 2,
"emailAddress": "john@gmail.com",
"type": 2,
"isUnread": true,
"labelIds": [
2
]
},
{
"id": 1,
"emailAddress": "nick@gmail.com",
"type": 1,
"isUnread": true,
"labelIds": [
1
]
}
],
"attachments": [
{
"name": "card.pdf",
"sizeInBytes": 129323
}
],
"_rid": "zl9jANa86aABAAAAAAAAAA==",
"_self": "dbs/zl9jAA==/colls/zl9jANa86aA=/docs/zl9jANa86aABAAAAAAAAAA==/",
"_etag": ""0d0093b8-0000-0100-0000-62a57c470000"",
"_attachments": "attachments/",
"recipients[0].isUnread": true,
"_ts": 1655012423
}

用于更新与特定电子邮件匹配的发件人或收件人的isUnread的条件修补程序代码。

var container = _cosmosClient.GetContainer("my-database", "Message");
// Get all of the messages that match the list of conversations to update
var queryResultSetIterator = container.GetItemLinqQueryable<Message2>()
.Select(x => new PatchMessageContainer
{
Id = x.Id,
ConversationId = x.ConversationId,
Recipients = x.Recipients,
Sender = x.Sender
})
.Where(x => payload.ConversationIds.Contains(x.ConversationId)).ToFeedIterator();
var conversations = new List<PatchMessageContainer>();
while (queryResultSetIterator.HasMoreResults)
conversations.AddRange(await queryResultSetIterator.ReadNextAsync().ConfigureAwait(false));
// Set isUnread for the authenticated user in the recipients list
var updateTasks = new List<Task>();
foreach (var conversation in conversations)
{
// The following Patch operations are smart enough to skip if the target value is already set to the desired value
var patchOpts = new List<PatchOperation>();
// Update sender isUnread if sender matches auth email
if (conversation.Sender.EmailAddress == userClaims.Email && conversation.Sender.IsUnread != payload.SetIsUnread)
patchOpts.Add(PatchOperation.Set($"/sender/isUnread", payload.SetIsUnread));
// Update recipient isUnread where recipient matches auth email
var idx = conversation.Recipients.FindIndex(x => x.EmailAddress == userClaims.Email);
if (idx > -1 && conversation.Recipients[idx].IsUnread != payload.SetIsUnread)
patchOpts.Add(PatchOperation.Set($"/recipients/{idx}/isUnread", payload.SetIsUnread));
// Send the actual patch request
var task = container.PatchItemAsync<Message2>(conversation.Id.ToString(),
new PartitionKey(conversation.ConversationId.ToString()), patchOpts);
updateTasks.Add(task);
}
await Task.WhenAll(updateTasks);

这里的conversations变量实际上只是第一个代码块中的Message文档,但我只选择了完成更新所需的字段子集。

希望这能有所帮助。

最新更新