9

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

4

2 回答 2

17

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

$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 个文档),但可以评估每个文档以过滤掉创建的额外文档(删除 { tags : 'cat' } from这个例子)。

HTH - 抢。

于 2013-03-25T03:19:53.880 回答
0

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

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

基本上他给出的例子:

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

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

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

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

于 2013-03-25T10:48:35.627 回答