对空值的匹配会导致MongoDB的查询需要回表并进行过滤,也就是说不被索引覆盖

编程语言 2026-07-10

https://mongoplayground.net/p/EDTWuPebIwm

db.collection.aggregate([
  {
    $match: {
      cheese: null
    }
  },
  {
    $project: {
      _id: 0,
      butter: 1
    }
  }
]).explain("queryPlanner")

MongoDB会返回在上述查询中字段cheese缺失或其值为null的文档。

MongoDB还在索引中把null当作该文档字段缺失或等于null时的值来存储。

因此,由于查询会返回字段缺失或为null的文档,为什么还需要先获取再过滤?当查询匹配 "cheese: { $exists: false }" 时存在歧义。但对于 "cheese: null",则不存在歧义。

       "filter": {
          "cheese": {
            "$eq": null
          }
        },

能否解释一下,上面的查询为何无法被索引覆盖?

是否有办法让查询像应该那样被覆盖,因为索引包含了覆盖该查询所需的所有信息?

解决方案

The index entry doesn't store a BSON with field names, only the values for the indexed fields. It doesn't distinguish between a missing field and a field with null value. Both are stored as a null key.

筛选阶段 $match: { cheese: null } 能匹配两者,但投影可能返回 {}{ cheese: null },而这些信息不在索引键中。于是就必须获取BSON文档。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章