Mongo将嵌入式文档转换为数组

Sid*_*rth 3 mongodb mongodb-query

有没有办法将嵌套文档结构转换为数组?以下是一个例子:

输入

"experience" : {
        "0" : {
            "duration" : "3 months",
            "end" : "August 2012",
            "organization" : {
                "0" : {
                    "name" : "Bank of China",
                    "profile_url" : "http://www.linkedin.com/company/13801"
                }
            },
            "start" : "June 2012",
            "title" : "Intern Analyst"
        }
    },
Run Code Online (Sandbox Code Playgroud)

预期产出:

"experience" : [
           {
            "duration" : "3 months",
            "end" : "August 2012",
            "organization" : {
                "0" : {
                    "name" : "Bank of China",
                    "profile_url" : "http://www.linkedin.com/company/13801"
                }
            },
            "start" : "June 2012",
            "title" : "Intern Analyst"
        }
    ],
Run Code Online (Sandbox Code Playgroud)

目前我正在使用脚本迭代每个元素,将它们转换为数组并最终更新文档.但这需要花费很多时间,有没有更好的方法呢?

Bla*_*ven 5

您仍然需要迭代内容,但您应该使用批量操作回写:

对于MongoDB 2.6及更高版本:

var bulk = db.collection.initializeUnorderedBulkOp(),
    count = 0;

db.collection.find({ 
   "$where": "return !Array.isArray(this.experience)"
}).forEach(function(doc) {
    bulk.find({ "_id": doc._id }).updateOne({
        "$set": { "experience": [doc.experience["0"]] }
    });
    count++;

    // Write once in 1000 entries
    if ( count % 1000 == 0 ) {
        bulk.execute();    
        bulk = db.collection.initializeUnorderedBulkOp();
    }
})

// Write the remaining
if ( count % 1000 != 0 )
    bulk.execute();
Run Code Online (Sandbox Code Playgroud)

或者在MongoDB 3.2及更高版本的现代版本中,该bulkWrite()方法是首选:

var ops = [];

db.collection.find({ 
   "$where": "return !Array.isArray(this.experience)"
}).forEach(function(doc) {
   ops.push({
       "updateOne": {
           "filter": { "_id": doc._id },
           "update": { "$set": { "experience": [doc.experience["0"]] } }
       }
   });

   if ( ops.length == 1000 ) {
       db.collection.bulkWrite(ops,{ "ordered": false })
       ops = [];
   }
})

if ( ops.length > 0 )
    db.collection.bulkWrite(ops,{ "ordered": false });
Run Code Online (Sandbox Code Playgroud)

因此,当通过游标写回数据库时,使用"无序"设置的批量写入操作是可行的方法.每批1000个请求只有一个写入/响应,这减少了大量开销,"无序"意味着写入可以并行发生,而不是按顺序发生.这一切都使它更快.