【问题标题】:Aggregation pipeline and indexes聚合管道和索引
【发布时间】:2013-03-14 11:18:39
【问题描述】:

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

【问题讨论】:

    标签: mongodb indexing aggregation-framework


    【解决方案1】:

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

    一旦您使用$project$group$unwind 更改文档,索引就不再有效/可用。

    如果您在数组字段上有索引,您仍然可以在 $unwind 之前使用它来加快选择要流水线的文档,然后使用第二个 $match 进一步细化所选文档。

    考虑以下文件:

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

    tags 上有一个索引。

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

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

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

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

    HTH - 抢劫。

    【讨论】:

    • 感谢您的回答。但是,我发现“一旦您使用 ...$unwind 改变文档,索引就不再有效”与其余答案相矛盾。你能解释一下为什么会这样吗?
    • 对不起,应该更清楚。我将尝试在一秒钟内对其进行编辑,但第一个匹配使用索引,第二个不会。
    【解决方案2】:

    嗯@Rob 确实给出了正确的答案,但我知道他是如何让你走错路的:

    如果您在数组字段上有索引,您仍然可以在 $unwind 之前和之后使用它来加快选择要流水线的文档,然后进一步细化所选文档。

    基本上是他给出的例子:

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

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

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

    因此,基本上,一旦您对文档进行了变异并将其加载到管道中,目前几乎不可能使用索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      相关资源
      最近更新 更多