所以这就是问题:
我在集合A中有文档,当它首次创建时,它没有被任何其他文档引用。在某些时候,将创建集合Bwill中的文档,它将引用集合A中的文档的ObjectId。
在集合B中找到I文档未引用的集合A中的所有文档的最佳方法是什么?
我理解MongoDB不支持连接,但我想知道除了从集合B获取所有引用的ObjectId并在集合A中查找不在该列表中的文档之外是否存在此问题的解决方案,因为此解决方案可能不会很好地扩展。
我可以将集合A中的文档嵌入到集合B的文档中,然后将其从集合A中删除吗?这是最好的解决方案吗?
感谢您的帮助和评论。
答案 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 } })