你可以在嵌套属性上使用Document.SetPropertyValue(string,string)吗?

时间:2017-04-01 00:23:01

标签: .net azure-cosmosdb

说出给定的DocumentDb文档,例如:

{
    "id": "CDC101",
    "title": "Fundamentals of database design",
    "authordetails": { 
       "Name" : "Dave",
       "Age : "33"
    },
    "credits":  10
}

如果我想使用SetPropertyValue更新authordetails.Name,我会使用什么语法?以下似乎并不像我期望的那样有效:

//Fetch the Document to be updated
Document doc = client.CreateDocumentQuery<Document>(collectionLink)
                            .Where(r => r.Id == "CDC101")    
                            .AsEnumerable()
                            .SingleOrDefault();

//Update some properties on the found resource
doc.SetPropertyValue("authordetails.Name", "Mike");

//Now persist these changes to the database by replacing the original resource
Document updated = await client.ReplaceDocumentAsync(doc);

我问的原因是:我必须在集合中的大量文档中更改单个属性(新要求),并且我试图在单独的进程中从队列中处理它们以避免UI超时。我认为是一个sproc,但是基于javascript,并且没有像mongo这样的批量upsert我没有找到合适的&amp;可扩展的方式来做到这一点我是NoSQL思维方式的新手,我感到非常困惑。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

这个方法对我有用: 您可以使用GetPropertyValue来读取和写入嵌套属性作为动态

//Fetch the Document to be updated
Document doc = client.CreateDocumentQuery<Document>(collectionLink)
                            .Where(r => r.Id == "CDC101")    
                            .AsEnumerable()
                            .SingleOrDefault();

dynamic AuthInfo = doc.GetPropertyValue<dynamic>("AuthInfo");
AuthInfo.Name = "mike";
doc.SetPropertyValue("AuthInfo", AuthInfo);

//Now persist these changes to the database by replacing the original resource
Document updated = await client.ReplaceDocumentAsync(doc); 

答案 1 :(得分:1)

SetPropertyValue不支持设置嵌套属性。您可以在Azure feedback forum提交此用户语音。目前,我们可以将文档作为对象进行查询,然后替换文档。请参阅以下代码:

var entity = client.CreateDocumentQuery<Cred>(UriFactory.CreateDocumentCollectionUri("<databaseid>", "<collectionid>")).Where(r => r.ID == "CDC101")
                        .AsEnumerable().SingleOrDefault();
entity.AuthInfo.Name = "mike";
await client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri("<databaseid>", "<collectionid>", entity.ID), entity);

这是我测试的课程:

public class Cred
{
    [JsonProperty(PropertyName = "id")]
    public string ID { get; set; }
    [JsonProperty(PropertyName = "title")]
    public string Title { get; set; }
    [JsonProperty(PropertyName = "credits")]
    public int Credits { get; set; }
    [JsonProperty(PropertyName = "authordetails")]
    public AuthDetail AuthInfo { get; set; }
}
public class AuthDetail
{
    [JsonProperty(PropertyName = "Name")]
    public string Name { get; set; }
    [JsonProperty(PropertyName = "Age")]
    public int Age { get; set; }
}

我们也可以使用商店产品来做到这一点:

// SAMPLE STORED PROCEDURE
function sample() {
var collection = getContext().getCollection();

// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
    collection.getSelfLink(),
    'SELECT * FROM root r',
    function (err, feed, options) {
        if (err) throw err;

        // Check the feed and if empty, set the body to 'no docs found', 
        // else take 1st element from feed
        if (!feed || !feed.length) getContext().getResponse().setBody('no docs found');
        else getContext().getResponse().setBody(JSON.stringify(feed[0]));
        var doc= feed[0];
        doc.authordetails.Name="mike";
        var isAccepted = collection.replaceDocument(feed[0]._self, doc);  
    });

if (!isAccepted) throw new Error('The query was not accepted by the server.');
}