内联/将其他集合组合成一个集合

时间:2014-03-26 21:07:38

标签: mongodb mongodb-query

我想结合两个mongodb集合。

基本上我有一个包含从另一个集合引用一个文档的文档的集合。现在我希望将其作为内联/嵌套字段而不是单独的文档。

所以只是提供一个例子:

收藏A:

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

3 个答案:

答案 0 :(得分:1)

我在控制台上建议这样简单的东西:

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,则会删除不必要的属性(_idcollectionAID)。最后,它使用$push运算符更新 collectionA 中的匹配文档,将文档从 B 添加到字段collectionB。如果该字段不存在,则会自动将其创建为包含新插入文档的数组。如果它确实作为数组存在,它将被追加。 (如果它存在,但不是一个数组,它将失败)。由于update来电未使用upsert,因此如果 collectionB 文档中的_id不存在,则不会发生任何事情。< / p>

您可以根据需要对其进行扩展以删除其他字段,或者如果 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"
}

答案 1 :(得分:0)

遗憾的是,mapreduce无法生成完整的文档。 https://jira.mongodb.org/browse/SERVER-2517

不知道为什么尽管有所有的关注,抱怨和赞成,他们还没有改变它。因此,您必须使用您选择的语言手动执行此操作。

希望您已将自己编入索引&#39; collectionAID&#39;这应该可以提高查询的速度。只需编写一次通过A集合一个文档的内容,加载_id然后从Collection B添加数组。

答案 2 :(得分:0)

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); })