有没有办法将嵌套文档结构转换为数组?以下是一个例子:
输入
"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"
}
},
预期输出:
"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"
}
],
目前我正在使用脚本迭代每个元素,将它们转换为数组&最后更新文件。但这需要花费很多时间,有没有更好的方法呢?
答案 0 :(得分: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();
或者在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 });
因此,当通过游标写回数据库时,使用"无序"进行批量写入操作。设置是要走的路。它是每批1000个请求中只有一个写/响应,这减少了很多开销,并且#34;无序"意味着写入可以并行发生,而不是按顺序发生。这一切都使它更快。
答案 1 :(得分:0)
查看此查询是否适用于您的MongoDB版本
对于MongoDB版本3.2 +:
db.doc.aggregate([
{$project:{experience:["$experience.0"]}}
])
MongoDB< 3.2:
db.doc.aggregate([
{$group: {_id:"$_id", experience:{$push:"$experience.0"}}}
])
它应该将您的文档转换为:
{
"_id" : ObjectId("56f1b046a65ea8a72c34839c"),
"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"
}
]
}
如果您想使用聚合框架永久地更改集合中的文档,那么这是一种更好的方法。
假设您的收藏集名称为doc
db.doc.aggregate([
{$group: {_id:"$_id", experience:{$push:"$experience.0"}}},
{$out: "doc"}
])
上面的查询将转换所有文档。
答案 2 :(得分:0)
对于mongoDB版本> 4.2:
db.doc.aggregate([{ $match: {'experience.0': { $exists: false } } },
{$project:{experience:["$experience.0"]}}, { $merge: { into: "doc", on: "_id" }
])
注意::这里我们将更新的字段/文档与现有文档合并,但不替换/更新整个文档,$merge
的默认行为是merge
找到匹配的文档后,您可以传递其他选项,例如replace / keepExisting等。
参考: $merge