MongoDB - 如何找到其他集合中未被文档引用的所有文档

时间:2012-05-23 02:36:40

标签: mongodb

所以这就是问题:

我在集合A中有文档,当它首次创建时,它没有被任何其他文档引用。在某些时候,将创建集合Bwill中的文档,它将引用集合A中的文档的ObjectId。

在集合B中找到I文档未引用的集合A中的所有文档的最佳方法是什么?

我理解MongoDB不支持连接,但我想知道除了从集合B获取所有引用的ObjectId并在集合A中查找不在该列表中的文档之外是否存在此问题的解决方案,因为此解决方案可能不会很好地扩展。

我可以将集合A中的文档嵌入到集合B的文档中,然后将其从集合A中删除吗?这是最好的解决方案吗?

感谢您的帮助和评论。

3 个答案:

答案 0 :(得分:7)

使用MongoDB 3.2,添加$lookup运算符可以实现这一目标:

db.a.aggregate(
[
    {
        $lookup: {
            from: "b", <-- secondary collection name containing references to _id of 'a'
            localField: "_id",  <-- the _id field of the 'a' collection
            foreignField: "a_id", <-- the referencing field of the 'b' collection
            as: "references"
        }
    },
    {
        $match: {
            references: []
        }
    }
]);

上述查询将返回集合a中没有集合b中的引用的所有文档。

但要小心这一点。性能可能会成为大型集合的问题。

答案 1 :(得分:4)

很多选择:

1)将B文档的id添加到A文档中的数组(反向引用)。现在,您可以查找该数组中没有任何元素的A文档。问题:如果您有大量交叉引用,则数组可能会因文档大小而过大。

2)添加一个跟踪A和B之间引用的集合C.表现得像一个连接表。

3)在'引用'中有一个简单的标志。当你添加一个B标记时,它引用的所有A都是“引用的”。当你删除B时,对它所引用的所有A进行B扫描并取消标记不再有引用的A。问题:可能会失去同步。

4)在B上使用map reduce创建一个集合,其中包含任何B引用的所有A的ID。使用该集合标记所有引用的A(在首先取消标记所有A之后)。可以用它来定期修复(3)。

5)将两种文档类型放在同一个集合中,并使用map reduce发出_id和一个标记,表示“在A中”或“由B引用”。在reduce步骤中,查找具有'in A'但不是'由B引用'的任何组。

...

答案 2 :(得分:1)

由于没有联接,所以你提到的唯一选择是:使用嵌入式文档,或者让自己使用两部分查询。

这取决于您的实现,但将文档类型B添加到A中的相应文档听起来是最好的选择。通过这种方式,您可以使用简单的查询($exists operator)来检索没有B的A ...

A.find( { B: { $exists: false } })