我想合并两个mongodb集合。
基本上,我有一个集合,其中包含引用另一个集合中的一个文档的文档。现在我想把它作为一个内联/嵌套字段,而不是一个单独的文档。
举个例子:
集合:
[{
"_id":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"someValue": "foo"
},
{
"_id":"5F0BB248-E628-4B8F-A2F6-FECD79B78354",
"someValue": "bar"
}]
收集B:
[{
"_id":"169099A4-5EB9-4D55-8118-53D30B8A2E1A",
"collectionAID":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"some":"foo",
"andOther":"stuff"
},
{
"_id":"83B14A8B-86A8-49FF-8394-0A7F9E709C13",
"collectionAID":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"some":"bar",
"andOther":"random"
}]
这应该导致集合A看起来像这样:
[{
"_id":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"someValue": "foo",
"collectionB":[{
"some":"foo",
"andOther":"stuff"
},{
"some":"bar",
"andOther":"random"
}]
},
{
"_id":"5F0BB248-E628-4B8F-A2F6-FECD79B78354",
"someValue": "bar"
}]
我建议从控制台中执行如下简单操作:
db.collB.find().forEach(function(doc) {
var aid = doc.collectionAID;
if (typeof aid === 'undefined') { return; } // nothing
delete doc["_id"]; // remove property
delete doc["collectionAID"]; // remove property
db.collA.update({_id: aid}, /* match the ID from B */
{ $push : { collectionB : doc }});
});
循环遍历collectionB中的每个文档,如果定义了字段collectionAID
,则删除不必要的属性(_id
和collectionAID
)。最后,它使用$push
操作符将B中的文档添加到字段collectionB
中,从而更新collectionA中的匹配文档。如果该字段不存在,它将自动创建为包含新插入文档的数组。如果它确实以数组的形式存在,它将被追加。(如果它存在,但不是数组,它将失败)。因为update
调用没有使用upsert
,如果collectionB文档中的_id
不存在,则不会发生任何事情。
您可以扩展它以删除其他必要的字段,或者可能添加更健壮的错误处理,例如,如果来自B的文档与 a 中的任何内容不匹配。
在数据上运行上面的代码会产生如下结果:
{ "_id" : "5F0BB248-E628-4B8F-A2F6-FECD79B78354", "someValue" : "bar" }
{ "_id" : "90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"collectionB" : [
{
"some" : "foo",
"andOther" : "stuff"
},
{
"some" : "bar",
"andOther" : "random"
}
],
"someValue" : "foo"
}
遗憾的是mapreduce不能生成完整的文档。https://jira.mongodb.org/browse/server - 2517
不知道为什么尽管所有的关注,抱怨和支持,他们没有改变它。因此,您必须使用您选择的语言手动执行此操作。
希望你已经索引'collectionAID',这应该提高你的查询速度。只需要写一些东西一次一个文档地遍历A集合,加载_id然后添加集合b中的数组
有比https://stackoverflow.com/a/22676205/1578508
快得多的方法您可以用另一种方式执行,遍历要插入文档的集合。(更少的执行!)
db.collA.find().forEach(function (x) {
var collBs = db.collB.find({"collectionAID":x._id},{"_id":0,"collectionA":0});
x.collectionB = collBs.toArray();
db.collA.save(x);
})