C# 更新BsonDocument中数组内部的元素
我有一份“受款人”B文件,如下所示:C# 更新BsonDocument中数组内部的元素,c#,mongodb,mongodb-.net-driver,C#,Mongodb,Mongodb .net Driver,我有一份“受款人”B文件,如下所示: { "Token" : "0b21ae960f25c6357286ce6c206bdef2", "LastAccessed" : ISODate("2012-07-11T02:14:59.94Z"), "Firstname" : "John", "Lastname" : "Smith", "PayrollInfo" : [{ "Tag" : "EARNINGS", "Value" : "744.11", }
{
"Token" : "0b21ae960f25c6357286ce6c206bdef2",
"LastAccessed" : ISODate("2012-07-11T02:14:59.94Z"),
"Firstname" : "John",
"Lastname" : "Smith",
"PayrollInfo" : [{
"Tag" : "EARNINGS",
"Value" : "744.11",
}, {
"Tag" : "DEDUCTIONS",
"Value" : "70.01",
}],
},
"Status" : "1",
"_id" : ObjectId("4fc263158db2b88f762f1aa5")
}
我根据收款人id检索此文档
var collection = database.GetCollection("Payee");
var query = Query.EQ("_id", _id);
var bDoc = collection.FindOne(query);
然后,我需要在不同的时间更新PayrollInfo数组中的特定对象。因此,我在数组中搜索具有适当“标记”的对象,并将“值”更新到数据库中。我使用以下逻辑来执行此操作:
var bsonPayrollInfo = bDoc["PayrollInfo", null];
if (bsonPayrollInfo != null)
{
var ArrayOfPayrollInfoObjects = bsonPayrollInfo.AsBsonArray;
for (int i = 0; i < ArrayOfPayrollInfoObjects.Count; i++)
{
var bInnerDoc = ArrayOfPayrollInfoObjects[i].AsBsonDocument;
if (bInnerDoc != null)
{
if (bInnerDoc["Tag"] == "EARNINGS")
{
//update here
var update = Update
.Set("PayrollInfo."+ i.ToString() + ".Value", 744.11)
collection.FindAndModify(query, null, update);
bUpdateData = true;
break;
}
}
}
}
if (!bUpdateData)
{
//Use Update.Push. This works fine and is not relevant to the question.
}
var bsonPayrollInfo=bDoc[“PayrollInfo”,null];
如果(bsonPayrollInfo!=null)
{
var arrayofpayrollinfobjects=bsonPayrollInfo.AsBsonArray;
对于(int i=0;i
所有这些代码都工作得很好,但我认为我在实现结果时太麻烦了。有没有更简洁的方法?本质上,我正在试图找到一种更好的方法来更新BsonDocument中数组内部的对象。Mongo有一个位置操作符,可以让您对数组中的匹配值进行操作。语法为:
field1.$.field2
下面是一个使用Mongo shell的示例:
db.dots.insert({tags: [{name: "beer", count: 2}, {name: "nuts", count: 3}]})
db.dots.update({"tags.name": "beer"}, {$inc: {"tags.$.count" : 1}})
result = db.dots.findOne()
{ "_id" : ObjectId("50078284ea80325278ff0c63"), "tags" : [ { "name" : "beer", "count" : 3 }, { "name" : "nuts", "count" : 3 } ] }
把我的答案放在这里,以防对你有帮助。根据@MrKurt的回答(谢谢!),下面是我对代码所做的修改
var collection = database.GetCollection("Payee");
var query = Query.EQ("_id", _id);
if (collection.Count(query) > 0)
{
//Found the Payee. Let's save his/her Tag for EARNINGS
UpdateBuilder update = null;
//Check if this Payee already has any EARNINGS Info saved.
//If so, we need to update that.
query = Query.And(query,
Query.EQ("PayrollInfo.Tag", "EARNINGS"));
//Update will be written based on whether we find the Tag:EARNINGS element in the PayrollInfo array
if (collection.Count(query) > 0)
{
//There is already an element in the PayrollInfo for EARNINGS
//Just update that element
update = Update
.Set("PayrollInfo.$.Value", "744.11");
}
else
{
//This user does not have any prior EARNINGS data. Add it to the user record
query = Query.EQ("_id", _id);
//Add a new element in the Array for PayrollInfo to store the EARNINGS data
update = Update.Push("PayrollInfo",
new BsonDocument {{"Tag", "EARNINGS"}, {"Value", "744.11"}}
);
}
//Run the update
collection.FindAndModify(query, null, update);
}
它看起来并不比我的原始代码差,但它更直观,我学到了很多关于位置操作符的知识 当我直接查询数组元素时,我看到了位置运算符的用法,但在我的例子中,我通过_id查询得到了一个Bsondocument。我需要在这个文档中找到我已经在手的数组元素。上面显示的我的原始代码运行良好。但是我想我可能缺少一个更好的解决问题的方法。你可以跳过所有的C#,只是发布一个更新,即使你已经有了文档。只需将查询设置为:{u id:[id],“PayrollInfo.Tag”:“EARNINGS”},并将该位置运算符作为更新文档发送出去。感谢您的指点。您帮助我找到了通过位置运算符实现的正确位置。