聚合管道和索引

时间:2013-03-25 03:05:26

标签: mongodb indexing aggregation-framework

http://docs.mongodb.org/manual/core/indexes/#multikey-indexes,可以使用多键索引在数组字段上创建索引。 http://docs.mongodb.org/manual/applications/aggregation/#pipeline-operators-and-indexes列出了如何在聚合框架中使用索引的一些方法。但是,有时我可能需要在数组字段上执行$unwind来执行$group。我的问题是,一旦在管道中间操作多键索引(或使用这种数组字段的任何索引)仍然可以使用吗?

2 个答案:

答案 0 :(得分:15)

通常,只有可以展平为普通查询($match$limit$sort$skip)的管道运营商才能使用索引一个集合。这是2.4中添加的$geoNear运算符必须位于管道开头的原因之一。

使用$project$group$unwind变更文档后,索引将不再有效/可用。

如果您在数组字段上有索引,您仍然可以在$unwind之前使用它来加速选择要管道的文档,然后使用第二个$match进一步优化所选文档。< / p>

考虑以下文件:

{ tags: [ 'cat', 'bird', 'blue' ] }

索引为tags

如果您只想对以b开头的标记进行分组,那么您可以执行以下聚合:

{ pipeline: [
      { $match : { tags : /^b/ } },
      { $unwind : '$tags' },
      { $match : { tags : /^b/ } },
      /* the rest */
  ] }

第一个$match使用tags上的索引进行粗粒匹配。

$unwind之后的第二个匹配将无法使用索引(上面的文档现在是3个文档),但可以评估每个文档以过滤掉创建的额外文档(删除{tag:'cat'}来自示例)。

HTH - Rob。

答案 1 :(得分:0)

嗯@Rob确实给出了正确的答案,但我知道他怎么能引导你走错路一点:

  

如果你有一个数组字段的索引,你仍然可以在$ unwind之前和之后使用它来加速选择要管道的文档,然后进一步细化所选文档。

基本上他给出的例子是:

{ pipeline: [
      { $match : { tags : /^b/ } },
      { $unwind : '$tags' },
      { $match : { tags : /^b/ } },
      /* the rest */
  ] }

不会使用超过$unwind的多键索引。因此,它将能够搜索标记名称以b开头的所有ROOT文档,但是,它将无法$unwind,然后在第二个$match中过滤子文档使用索引。

$match仅适用于变异前的索引。

所以基本上一旦你改变了文档并将其加载到管道上,当前几乎不可能使用索引。