在聚合框架中使用索引-了解文档

Youtix

我正在阅读MongoDB文档,更确切地说是聚合管道。当我阅读本章,更准确地说,这句话时:

即使管道使用索引,聚合仍然需要访问实际文档;即索引不能完全覆盖聚合管道。

我不太明白这句话的意思。他们是说它可以在第一阶段使用索引,但在以后无法使用它吗?那么,为什么索引不能完全覆盖聚合管道呢?

有人可以给我一个很好且容易理解的示例,以及一个反例吗?

先感谢您 !

尼尔·伦恩

这需要对MongoDB中的“覆盖索引”查询实际上是什么有一点了解,并且许多人会弄错这一点。取得以下文件:

{ "a": 1, "b": 2 }

大多数人会犯的错误是,即使将这两个字段都添加到索引中,例如:

db.collection.ensureIndex({ "a": 1, "b": 1 })

然后他们认为这会导致“覆盖索引”查询:

db.collection.find({ "a": 1, "b": 2 }).explain(); // bah-wah!!!

但事实并非如此。原因基本上是,作为“无模式”数据存储,MongoDB无法知道“ a”和“ b”实际上是集合中每个文档中唯一的字段。因此,如果没有“投影”操作也排除_id索引中不存在字段,那么优化器可能无法知道索引包含检索此数据所需的所有信息。因此,除非您执行以下操作,否则它必须返回到集合:

db.collection.find({ "a": 1, "b": 2 },{ "_id": 0, "a": 1, "b": 1 }).explain(); // success!!!

那么这如何适用于聚合呢?与不同的“管道”阶段一样,没有实际的方法可以真正完成与上述相同的组合。您唯一可以做的基本上是这样的:

db.collection.aggregate([
    { "$match": { "a": 1, "b": 2 } },
    { "$project": { "_id": 0, "a": 1, "b": 1 } }
])

重要的是要使用“ unix pipe”或|“ chaining”命令,因此即使进行了一些优化,也不是完全一样。每个管道阶段都会“传递”来自进行阶段的输出,这意味着_id(例如,此处)实际上并没有$match以优化的方式从前一个阶段“提取” ,即使您告诉它“离开”了。

由于$match诸如此类的其他特殊阶段$geoNear实际上是唯一真正可以访问索引的事物,因此,由于“字段排除”实际上并不可用,因此您不会真正获得“覆盖索引”结果。

在这里要说的最后一件事是,聚合实际上不是基本查询的“替代品”,因此不应该这样使用。您应该已经接受“正在这里做更多的工作”,并且“覆盖索引”并不是您真正想要的,因为您通常想要的数据比索引中的数据还要多。

如果所有内容都在索引中,那么它实际上可能不是聚合操作,并且最好使用basic来执行.find(),即使这意味着重新构造模式表示。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章