Mongodb 仅返回与Mongo聚合匹配的子文档

Mongodb 仅返回与Mongo聚合匹配的子文档,mongodb,mongoose,Mongodb,Mongoose,我有一个带有子文档的模式 // Schema var company = { _id: ObjectId, publish: Boolean, divisions: { employees: [ObjectId] } }; 我需要找到与我的查询匹配的所有子文档分区。似乎我必须使用2个匹配项—一个用于筛选出初始文档,另一个用于从生成的$unwind操作中筛选出匹配的子文档。有没有更有效的方法 // Query this.aggregate({ $match: {

我有一个带有子文档的模式

// Schema
var company = {
  _id: ObjectId,
  publish: Boolean,
  divisions: {
    employees: [ObjectId]
  }
};
我需要找到与我的查询匹配的所有子文档分区。似乎我必须使用2个匹配项—一个用于筛选出初始文档,另一个用于从生成的$unwind操作中筛选出匹配的子文档。有没有更有效的方法

// Query
this.aggregate({
    $match: {
    'publish': 1,
    'divisions.employees': new ObjectId(userid)
    }
  }, {
    $unwind: '$divisions'
  }, {
    $match: {
      'divisions.employees': new ObjectId(userid)
    }
  }

我找到了这个,但我不确定它是否符合我的需要。

在这里进行两项匹配是正确的。您可以取消第一个匹配阶段,只需放松,但使用初始$match允许您将管道缩小到至少生成一个输出文档的文档,即publish:true和某些员工ObjectId与给定ObjectId匹配的文档。您将能够使用索引,如{publish:1,divisions.employees:1}上的索引,快速执行第一个匹配阶段

但是,您应该问问自己,为什么在这里使用聚合管道,以及它是否合适。您是否通常会查询属于publish:1公司一部分的给定员工?这是您用例的主要查询之一吗?如果不频繁或不重要,那么聚合是一种很好的方法。否则,您应该重新考虑模式。您可以使用以下模式简化此查询

{
    "_id" : ObjectId,
    "publish" : Boolean,
    "company" : (unique identifier, possibly a String or ObjectId)
}
将员工建模为文档,并将公司信息非规范化为员工文档。那么您的查询就和

db.employees.find{u id:ObjectIduserid,publish:true}


这将比聚合快得多,而不是聚合速度慢;这只是相对更快。我不是要你这样做-使用你自己对用例的了解来做出正确的决定。

谢谢-我不这样做,因为我真正的代码要复杂得多。因此,您建议的最有效的方法是在两个匹配中维护division.employee查询,只需添加一个索引?我不确定我是应该让部门员工兼任还是第二任。我认为两者都是最好的。第一个$match是使用索引并使下一步处理尽可能少的文档的机会,而第二个$match中的条件是获得正确结果所必需的。