更新来自另一个集合的匹配记录

update matched records from another collection?

本文关键字:记录 集合 另一个 更新      更新时间:2023-09-26

有人能帮我更新基于另一个集合吗?我有一个像这样的皮卡收集。

{
    "_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})

谢谢你的帮助。

我应该按照完全相反的顺序来循环,因为这样会更有效率:

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 } }
        );
    });
});
在mongodb 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"集合中作为数组拉到内存中,因此只有每个文档从游标结果中拉入。

Bulk操作操作将"更新"存储在可管理的块中,这些块应该低于16MB BSON限制,然后您将这些块发送,而不是单独的更新。驱动程序实现应该处理大部分这些,但是为了安全起见,添加了一些"自我管理"。