我有一个带有subdocs的模式。
// Schema
var company = {
_id: ObjectId,
publish: Boolean,
divisions: {
employees: [ObjectId]
}
};
我需要找到与我的查询匹配的所有subdocs(分区)。似乎我必须使用2个匹配 - 一个用于过滤掉初始文档,第二个用于从生成的$ unwind操作中过滤掉匹配的子文件。有更有效的方法吗?
// Query
this.aggregate({
$match: {
'publish': 1,
'divisions.employees': new ObjectId(userid)
}
}, {
$unwind: '$divisions'
}, {
$match: {
'divisions.employees': new ObjectId(userid)
}
}
我发现了ticket,但我不确定这是否符合我的要求。
答案 0 :(得分:0)
这两场比赛都是正确的。您可以消除第一个匹配阶段并且只是展开,但是使用初始$ match允许您将管道缩小到精确到那些将生成至少一个输出文档的文档(即那些publish : true
和{employees
的文档。 {1}} ObjectId匹配给定的ObjectId)。您将能够使用索引(如{ publish : 1, divisions.employees : 1 }
上的索引)快速执行第一个匹配阶段。
但是,您应该问问自己为什么在这里使用聚合管道以及它是否合适。您是否通常会查询属于publish : 1
公司的特定员工?这是您的用例的主要查询之一吗?如果它不常见或不重要,那么聚合是一种很好的方法。否则,您应该重新考虑架构。您可以使用类似
{
"_id" : ObjectId,
"publish" : Boolean,
"company" : (unique identifier, possibly a String or ObjectId)
}
将员工建模为文档,并将公司信息非正规化为员工文档。然后您的查询就像
一样简单db.employees.find({“_ id”:ObjectId(userid),“publish”:true})
这将比聚合快得多(不是聚合会慢;这只是相对较快)。我并没有告诉你这样做 - 使用你自己的用例知识来做出正确的电话。