我有一个文档集合,每个文档都包含array.我想要的输出是按特定条件过滤的展开的数组元素.

我可以通过执行以下操作来实现此目的:

db.collection.aggregate([
 {
   $unwind: "$myArrayField"
 },
 {
   $match: {
     "myArrayField.myCriteriaField": "myValue"
   }
 }
])

但放松一切似乎是浪费,所以我就这么做了

db.collection.aggregate([
 {
   $match: {
     "myArrayField.myCriteriaField": "myValue"
   }
 },
 {
   $unwind: "$myArrayField"
 },
 {
   $match: {
     "myArrayField.myCriteriaField": "myValue"
   }
 }
])

要筛选出可行的候选文档,请展开这些文档,然后再次筛选展开的元素,因为会有不匹配的元素.

或者,我可以这样做

db.collection.aggregate([
 {
  $project: {
    myArrayField: {
      $filter: {
        input: "$myArrayField",
        as: "element",
        cond: { $eq: ["$$element.myCriteriaField", "myValue"] }
      }
    }
  }
 },
 {
  $unwind: "$myArrayField"
 }
])

甚至是

db.collection.aggregate([
  {
   $match: {
     "myArrayField.myCriteriaField": "myValue"
   }
 },
 {
  $project: {
    myArrayField: {
      $filter: {
        input: "$myArrayField",
        as: "element",
        cond: { $eq: ["$$element.myCriteriaField", "myValue"] }
      }
    }
  }
 },
 {
  $unwind: "$myArrayField"
 }
])

哪一个是最有效率的?我不太了解聚合是如何运行的,不知道它可能依赖于哪些变量(集合大小、文档大小等).

最后,比赛取消比赛看起来很简单,但不得不这样做也感觉不对,所以我想知道我是不是错过了什么.

推荐答案

首先,您必须确保在该领域有一个索引.用Explain来判断第一阶段$match的指数命中率.

现在,我们解释一下你的2个建议:$project $filter $unwind vs $match $project $filter $unwind:

  • $project $filter $unwind:在第一阶段$project中,MongoDB正在进行集合扫描,将该集合中的ALL documents与该字段一起输出.现在,它是full collection scanslow

  • $match $project $filter $unwind:在第一阶段$match中,MongoDB在命中索引时执行的是索引扫描而不是收集.在此之后,阶段$project将在limit document上做匹配.现在,它是index scanfaster,因为MongoDB只对某些文档执行操作.

最后,你的第二个 Select ,第二个更好

Mongodb相关问答推荐

在MongoDB中获取所有帖子时如何获取相关用户信息

Tableau 与 Mongo DB Atlas by MongoDB 的连接缓存问题

Spring Boot 升级后未映射 Mongo 模板结果

我可以在 MongoDB 中将字段值设置为对象键吗?

如何将以下聚合查询转换为 bson 并在 golang 中执行

MongoError:$subtract 累加​​器是一元运算符

Mongo 可尾游标与 Redis 发布/订阅

使用 ObjectId.GenerateNewId() 还是离开 MongoDB 创建一个?

通过 Spring Boot 应用程序访问 mongodb 时的身份验证错误

在 mongodb 中查找字段的所有非不同值

如何在我的Meteor 应用程序数据库中使用 mongoimport?

RoR3 上的 Mongoid:1)如何在查询中返回特定字段? 2)需要什么 inverse_of ?

嵌套数组内的Mongodb增量值

Mongo Schema-less集合和 C#

Mongoose / MongoDB 用户通知方案建议

Mongodb错误:The positional operator did not find the match needed from the query

如何向 mongodb 2.6 添加身份验证?

无法连接到远程服务器上的 mongo

在 MongoDB 中快速搜索数十亿个小文档的策略

在 mongoose 中使用 UUID 进行 ObjectID 引用