我尝试通过服务器端的存储过程更新cosomosdb中的大量复杂文档。我的客户端是用C#开发的。
我想实现存储过程,更新课程的详细信息到学生列表,我想更新所有属于id列表的学生的课程详细信息给出课程详细信息
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");
}
}
}
谢谢。
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"
}