如何使用C#更新cosmos db中文档中的特定子值?

时间:2018-10-02 15:17:57

标签: azure-cosmosdb

我在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);

现在如何更新文档以在cosmosdb中反映新的属性值?

任何帮助将不胜感激

1 个答案:

答案 0 :(得分:0)

有多种方法可以做到这一点。如果您不想执行任何特定的对象映射,而只想使用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对象,其分区键值为该文档的分区键。

这既便宜又便宜。