通过复杂类型cosmosDB azure的存储过程进行批量更新

问题描述 投票:0回答:1

我尝试通过服务器端的存储过程更新cosomosdb中的大量复杂文档。我的客户端是用C#开发的。

我想实现存储过程,更新课程的详细信息到学生列表,我想更新所有属于id列表的学生的课程详细信息给出课程详细信息

  1. 我如何创建返回id包含在ids参数中的所有文档的查询。

2.如何更新复杂对象,例如:

   public class CourseDetiels : Microsoft.Azure.Documents.Resource
{
    [JsonProperty("name")]
    public String CName { get; set; }

    [JsonProperty("finalGrade")]
    public double FinalGrade{ get; set; }
    [JsonProperty("GradesInWorks")]
    public double[] GradesInWorks{ get; set; }

}

我需要在学生班的课程词典中更新用户在特定学期中所学的课程:

    public class Student: Microsoft.Azure.Documents.Resource
{
    [JsonProperty(PropertyName = "id")]
    public String ID { get; set; }
    [JsonProperty(PropertyName = "Courses")]
    public Dictionary<string, CourseDetiels> Courses{ get; set; }

}

这是我想写的伪代码....

function UpdateCourses(ids,courseDetiels) {

   var collection = getContext().getCollection();
   var collectionLink = collection.getSelfLink();
   var response = getContext().getResponse();
   var docCount = 0;
   var counter = 0;

   UpdateCoursesByIds(ids,complexObject);

   function UpdateCoursesByIds(ids,complexObject,continuation) {
        var query = {
            query: "select * from root c where ...." **//how to select only documents that contains in ids??**
        };

        var requestOptions = {
            continuation: continuation
        };

        var isAccepted =
            collection
            .queryDocuments(collectionLink,
                            query,
                            requestOptions,
                            function queryCallback(err, documents, responseOptions) {
                                     if (err) throw err;
                                     if (documents.length > 0) {
                                        // If at least one document is found, update it.
                                        docCount = documents.length;
                                        for (var i=0; i<docCount; i++){
                                            UpdateDoc(documents[i]);
                                        }
                                        response.setBody("Updated " + docCount + " documents");
                                      }
                                      else if (responseOptions.continuation) {
                                        UpdateCoursesByIds(responseOptions.continuation);
                                      } else {
                                             throw new Error("Document not found.");
                                             }
                            });

        if (!isAccepted) {
            throw new Error("The stored procedure timed out");
        }
    }

    function UpdateDoc(document) {
        //Optimistic concurrency control via HTTP ETag.
        var requestOptions = { etag: document._etag };

        **//I NEED TO UPDATE ONLY THE COURSES THAT TAKEN ....**

        var isAccepted = collection
                         .replaceDocument(document._self,
                                          document,
                                          requestOptions,
                                          function replaceCallback(err, updatedDocument, responseOptions) {
                                                   if (err) throw err;
                                                   counter++;
                                           });

        // If we hit execution bounds - throw an exception.
        if (!isAccepted) {
            throw new Error("The stored procedure timed out");
        }
    }
}

谢谢。

javascript c# azure stored-procedures azure-cosmosdb
1个回答
1
投票

1.如何创建返回id包含在ids参数中的所有文档的查询。

您可以在Azure Cosmos SQL APIs中使用IN运算符,如下所示:

SELECT * FROM c WHERE c.id in(“1”,“2”,....,“10”)

var idsArrString="";
for(var i = 0;i<ids.length;i++){
   idsArrString+="'"+ids[i]+"',";
}

idsArrString=idsArrString.substr(0,idsArrString.length-1);

var query = {
   query: "select * from root c where c.id in ("+ idsArrString + ")";
};

2.如何更新复杂对象

根据您的需要,我创建了一个存储过程如下:

    function sample(idsArrayString,courses) {
        var collection = getContext().getCollection();

        // Query documents as you want
        var isAccepted = collection.queryDocuments(
            collection.getSelfLink(),
// 1:Please replace the ("1","2") with your idsArrayString

            'SELECT * FROM root r where r.id in ("1","2")',
            function (err, feed, options) {
                if (err) throw err;
                if (!feed || !feed.length) getContext().getResponse().setBody('no docs found');
                else {
                    for(var i = 0;i<feed.length;i++){
                        var doc = feed[i];
// 2:Please replace "maths" with your courses obj
                        doc.course = "maths";
                        collection.replaceDocument(doc._self,doc,                           function(err) {
                                 if (err) throw err;
                     });
                    }
                    getContext().getResponse().setBody(JSON.stringify("success"));
                }
            });

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

请注意,代码中的两个注释用您自己的参数替换它们。

然后,您可以在C#代码中执行存储过程:

// execute the stored procedure
client.executeStoredProcedureAsync('dbs/testdb/colls/testColl/sprocs/<your stored procedure id>')
    .then(function (response) {
        console.log(response.result); 
    }, function (err) {
        console.log("Error", error);
    });

更多细节,请参阅此official tutorial

希望它能帮到你。


更新答案:

您可以使用上面的注释2更新doc中的课程详细信息:

doc.courseDetails.finalGrade = "50";

请参阅我提供的document中提到的示例代码,如下所示

client.executeStoredProcedureAsync('dbs/testdb/colls/testColl/sprocs/createMyDocument',
              <your arguments>);

更新答案2:

我提供了您提供的示例文档。

{
    "id": "4",
    "StudenName": "Jay",
    "Courses": {
        "Math": {
            "Grade": "A",
            "Place": "NYU"
        },
        "Phys": {
            "Grade": "B",
            "Place": "MIT"
        }
    },
    "Rank": "AA"
}

然后我修改上面存储过程javascript代码中的注释2,用“C”替换成绩。

for(var i = 0;i<feed.length;i++){
                    var doc = feed[i];
                    var cources = doc.Courses;
                    for (var key in cources) {
                        if (cources.hasOwnProperty(key)) {
                            console.log(key + " -> " + cources[key]);
                            cources[key].Grade ="C";
                        }
                    }
                    doc.Courses = cources;
                    collection.replaceDocument(doc._self,doc, 
                    function(err) {
                             if (err) throw err;
                 });
                }

更改文件:

{
    "id": "4",
    "StudenName": "Jay",
    "Courses": {
        "Math": {
            "Grade": "C",
            "Place": "NYU"
        },
        "Phys": {
            "Grade": "C",
            "Place": "MIT"
        }
    },
    "Rank": "AA"
}
© www.soinside.com 2019 - 2024. All rights reserved.