如何在mongodb中更新多个数组对象。 之前曾问过这个问题 - How to Update Multiple Array elements in mongodb
但这对我不起作用。我有一个对象数组
{
"_id" : ObjectId("4d2d8deff4e6c1d71fc29a07"),
"user_id" : "714638ba-2e08-2168-2b99-00002f3d43c0",
"events" : [
{
"handled" : {
"name": "Mike",
"visibile": false
},
"profile" : 10,
"data" : "....."
}
{
"handled" : {
"name": "Shaun",
"visibile": false
},
"profile" : 10,
"data" : "....."
}
{
"handled" : {
"name": "Glen",
"visibile": true
},
"profile" : 20,
"data" : "....."
}
...
]
}
我想将所有events.handled.visible:false更新为“events.handled.visible”:true。
我试过
collection.aggregate({
$match: {
_id: ObjectId("4d2d8deff4e6c1d71fc29a07")
}
}, {
$unwind: "$events"
}, {
"$match": {
"events.handled.visible": false
}
}, {
"$group": {
"_id": "$_id",
"count": {
"$sum": 1
}
}
}, {
"$group": {
"_id": null,
"count": {
"$max": "$count"
}
}
}, function(err, res) {
var max = res[0].count;
while (max--) {
collection.update({
"events.handled.visible": 1
}, {
"$set": {
"events.$.handled.visible": true
}
}, {
"multi": true
}, function(err, res) {
if (err) {
console.log("Whoops! " + err)
} else {
console.log("Yay! " + res)
}
})
}
} //End Function
) //End Aggregate
但那并没有更新任何东西。我错过了什么?
答案 0 :(得分:3)
虽然我不认为迭代预期计数是“最佳”方式,但这里基本上是对您尝试做的更正,在节点async
库的帮助下用于流量控制:
async.waterfall(
[
function(callback) {
collection.aggregate(
[
{ "$match": { "_id": ObjectId("4d2d8deff4e6c1d71fc29a07") } },
{ "$unwind": "$events" },
{ "$match": { "events.handled.visibile": false } },
{ "$group": {
"_id": "$_id",
"count": { "$sum": 1 }
}}
],
callback
);
},
function(results,callback) {
console.log(results);
var result = results[0];
async.whilst(
function() { return result.count-- },
function(callback) {
collection.update(
{ "_id": result._id, "events.handled.visibile": false },
{ "$set": { "events.$.handled.visibile": true } },
callback
)
},
callback
);
}
],
function(err) {
if (err) throw err;
// finished now
}
);
所以这里的主要内容是你的.update()
语句应该寻找"events.handled.visibile": false
匹配,当然你需要确保操作“串联”执行,否则没有真实地保证你实际上是从以前的.update()
改变状态抓取文档。
async.whilst
处理流控制,以便等待每个.update()
完成,直到执行下一个true
。当它的第一个逻辑语句是.update()
(计数器耗尽)并运行所有List<Integer> result = models.stream().collect(ArrayList::new, (r, p) -> {
switch (p.getState()) {
case 1:
r.add(p.getLeft());
break;
case 2:
r.add(p.getRight());
break;
case 3:
r.add(p.getLeft());
r.add(p.getRight());
break;
default:
r.add(p.getLeft());
break;
}
}, ArrayList::addAll);
语句时,循环将释放到最终的回调。
如果可能,您应该使用answer that you are following中引用的“批量”更新操作。这会发送所有更新,只有一个响应,因此消除了等待每个操作完成的开销。