有人可以帮我更新基于另一个的收藏吗?我有一个像这样的皮卡系列。
{
"_id": {
"$oid": "53a46be700b94521574b6f75"
},
"created": {
"$date": 1403236800000
},
"receivers": [
{
"model": "somemodel1",
"serial": "someserial1",
"access": "someaccess1"
},
{
"model": "somemodel2",
"serial": "someserial2",
"access": "someaccess2"
},
{
"model": "somemodel3",
"serial": "someserial3",
"access": "someaccess3"
}
],
"__v": 0
}
我想迭代接收器数组并搜索另一个集合中的每个访问,如果找到则添加它所在的活动。
这是我想要搜索的工作人员集合。
{
"_id": {
"$oid": "53af72481b2aeade0b46d025"
},
"activityNumber": "someactivity",
"date": "06/28/2014",
"lines": [
{
"Line #": "1",
"Access Card #": "someaccess1"
},
{
"Line #": "2",
"Access Card #": "someaccess2"
},
{
"Line #": "3",
"Access Card #": "someacess3"
}
],
}
这就是我想要的结果。
{
"_id": {
"$oid": "53a46be700b94521574b6f75"
},
"created": {
"$date": 1403236800000
},
"receivers": [
{
"model": "somemodel1",
"serial": "someserial1",
"access": "someaccess1",
"activityNumber": "someactivity"
},
{
"model": "somemodel2",
"serial": "someserial2",
"access": "someaccess2",
"activityNumber": "someactivity"
},
{
"model": "somemodel3",
"serial": "someserial3",
"access": "someaccess3",
"activityNumber": "someactivity"
}
],
"__v": 0
}
我创建了一个包含拾取器所有访问权限的数组。
var prodValues = db.pickups.aggregate([
{ "$unwind":"$receivers" },
{ "$group": {
"_id": null,
"products": { "$addToSet": "$receivers.access"}
}}
])
我可以轻松地遍历数组并搜索工作人员收集并返回其使用的活动。但我不确定如何在找到时执行查找并更新拾取集合。
db.workorders.find({ "lines.Access Card #": { "$in": prodValues.result[0].products }},{activityNumber:1})
感谢您的帮助。
答案 0 :(得分:1)
真的,我会以完全相反的顺序循环这个,因为它应该更有效:
var result = db.workorders.aggregate([
{ "$project": {
"activityNumber": 1,
"access": "$lines.Access Card #",
}}
]).result;
result.forEach(function(res) {
res.access.forEach(function(acc) {
db.pickups.update(
{ "receivers.access": acc },
{ "$set": { "receivers.$.activityNumber": res.activityNumber } }
);
});
});
使用MongDB 2.6,您可以通过聚合输出上的游标和批量操作API的使用来清理它:
var batch = db.pickups.initializeOrderedBulkOp();
var counter = 0;
db.workorders.aggregate([
{ "$project": {
"activityNumber": 1,
"access": "$lines.Access Card #",
}}
]).forEach(function(res) {
res.access.forEach(function(acc) {
batch.find({ "receivers.access": acc }).updateOne(
{ "$set": { "receivers.$.activityNumber": res.activityNumber } }
);
});
if ( counter % 500 == 0 ) {
batch.execute();
var batch = db.pickups.initializeOrderedBulkOp();
counter = 0;
}
});
if ( counter > 0 )
batch.execute();
无论哪种方式,您基本上都匹配文档和数组在第一个聚合查询和当前行返回的“access”值上的位置。这允许更新指定位置的相关信息。
MongoDB 2.6的改进是你没有把所有结果从“workoders”集合中拉出来作为一个数组存储到内存中,所以只有每个文档都从游标结果中拉入。
批量操作操作将“更新”存储在可管理的块中,这些块应低于16MB BSON限制,然后在这些块中发送,而不是单独更新。驱动程序实现应该处理大部分内容,但为了安全起见,还添加了一些“自我管理”。