使用更新操作将字段转换为数组

ggr*_*ner 3 mongodb mongodb-query

在 Mongo 中,如何仅使用update操作将字段转换为仅包含原始值的数组?

给定一个文件:

{
  "field": "x"
}
Run Code Online (Sandbox Code Playgroud)

然后进行一项或多项更新操作:

db.items.update(...)
Run Code Online (Sandbox Code Playgroud)

应该导致:

{
    "field": ["x"]
}
Run Code Online (Sandbox Code Playgroud)

Nei*_*unn 5

MongoDB 当前不允许您在更新类型的操作中引用字段的现有值。为了进行引用现有字段值的更改,您需要循环结果。但是数组转换部分很简单:

db.collection.find().forEach(function(doc) {
    db.collection.update(
        { _id: doc._id },
        { "$set": { "field": [doc.field] } }
    );
})
Run Code Online (Sandbox Code Playgroud)

或者甚至更好地使用 MongoDB 2.6 中的批量更新功能:

var batch = [];
db.collection.find().forEach(function(doc) {
     batch.push({
        "q": { _id: doc._id },
        "u": { "$set": { "field": [doc.field] } }
    });

    if ( batch.length % 500 == 0 ) {
        db.runCommand({ "update": "collection", "updates": batch });
        batch = [];
    }
});

if ( batch.length > 0 )
    db.runCommand({ "update": "collection", "updates": batch });
Run Code Online (Sandbox Code Playgroud)

或者甚至使用新的 Bulk API 助手:

var counter = 0;
var bulk = db.collection.initializeUnorderedBulkOp();
db.collection.find().forEach(function(doc) {
     bulk.find({ _id: doc._id }).update({
         "$set": { "field": [doc.field] } 
    });
    counter++;

    if ( counter % 500 == 0 ) {
        bulk.execute();
        bulk = db.collection.initializeUnorderedBulkOp();
        counter = 0;
    }
});

if ( counter > 0 )
    bulk.execute();
Run Code Online (Sandbox Code Playgroud)

最后两个只会每 500 个项目或任何您想将其调整到 16MB BSON 限制以下的项目将更新发送到服务器。所有更新仍然单独执行,但这从整体操作中删除了大量写入/确认流量,并且速度要快得多。