azure-cosmosdb之如何使用 C# 更新 cosmos db 文档中的特定子值

JustinYoung 阅读:66 2025-06-02 22:19:02 评论:0

我在 cosmos db 中有一个文档需要更新,类似于下面的文档

{ 
    "userId": "1234", 
    "values": { 
        "A": { 
            "description": "first description", 
            "timestamp": "2018-10-01T12:13:09.000Z", 
            "value": 5000, 
            "valueWithUnit": "202 W" 
        }, 
        "B": { 
            "description": "second description", 
            "timestamp": "2018-10-01T12:13:09.000Z", 
            "value": 2, 
            "valueWithUnit": "2.00 %" 
        } 
     }, 
    "id": "1", 
    "lastUpdate": "2018-09-20T14:39:00Z", 
    "_rid":  "rid", 
    "_self": "self", 
    "_etag": "etag", 
    "_attachments": "attachments/", 
    "_ts": 1234 
} 

我需要将“B”中的值从 2 更新为 3。

下面是我到目前为止的代码..

public DocumentClient client = new DocumentClient(new Uri(EndpointUrl), PrimaryKey); 
 
var collectionLink = UriFactory.CreateDocumentCollectionUri(databaseName, collectionName); 
 
Document doc = client.CreateDocumentQuery<Document>(collectionLink) 
            .Where(r => r.Id == "1") 
            .AsEnumerable() 
            .SingleOrDefault(); 
 
Document doc1 = doc.GetPropertyValue<Document>("values"); 
 
Document doc2 = doc1.GetPropertyValue<Document>("B"); 
 
doc2.SetPropertyValue("value", 3); 

我现在如何更新文档以反射(reflect) cosmosdb 中的新属性值?

任何帮助将不胜感激

请您参考如下方法:

有多种方法可以做到这一点。如果您不想做任何特定的对象映射,而只想使用 json,那么您的代码应该如下所示:

public DocumentClient client = new DocumentClient(new Uri(EndpointUrl), PrimaryKey); 
 
var collectionLink = UriFactory.CreateDocumentCollectionUri(databaseName, collectionName); 
 
Document doc = client.CreateDocumentQuery<Document>(collectionLink) 
            .Where(r => r.Id == "1") 
            .AsEnumerable() 
            .SingleOrDefault(); 
 
var docValues = doc.GetPropertyValue<dynamic>("values"); 
docValues.B.value = 3; 
doc.SetPropertyValue("values", docValues); 
 
await documentClient.ReplaceDocumentAsync(doc); 

如果您将 Document 对象与 GetPropertyValue 方法一起使用,您还会添加所有文档元数据,这不是您想要的。

请记住,如果您的集合是分区的,那么您还需要通过如下替换来提供分区键:

await documentClient.ReplaceDocumentAsync(doc, new RequestOptions{PartitionKey = new PartitionKey("partitionKeyValueHere")}); 

您还可以使用 UpsertDocumentAsync,如果文档不存在则插入,如果存在则更新。

var documentLink = UriFactory.CreateDocumentUri(databaseName, collectionName, "1"); 
await documentClient.UpsertDocumentAsync(documentLink, doc); 

如果集合是分区的:

var documentLink = UriFactory.CreateDocumentUri(databaseName, collectionName, "1"); 
await documentClient.UpsertDocumentAsync(documentLink, doc, new RequestOptions{PartitionKey = new PartitionKey("partitionKeyValueHere")}); 

您还可以通过将其转换为直接读取来加快查询逻辑。

您可以通过执行以下操作简单地使用它的 id 获取文档:

var docUri = UriFactory.CreateDocumentUri(databaseName, collectionName, "1"); 
Document doc = await productStore.CosmonautClient.DocumentClient.ReadDocumentAsync(docUri); 

如果您的集合已分区,您将需要带有分区键值的 RequestOptions 对象作为此文档的分区键。

这既更快又更便宜。


标签:C#
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号