当使用正则表达式执行$ elemMatch时,Mongo利用索引

时间:2012-02-15 12:20:01

标签: regex mongodb indexing

我有一个非常类似的模型:

文件发布

  • 有一个嵌入式数组ReleaseDetails []

  • ReleaseDetails数组包含ReleaseDetails类型的文档

  • ReleaseDetails文档有一个名为ArtistName的字段

  • ReleaseDetails文档有一个名为Type of text text

  • 的字段

我基本上想要这样做:

检索在其ReleaseDetails数组中有条目的所有Release文档,其中(两者)具有ArtistName = someRegexExpression AND Type = someOtherRegexExpression。基本上我这样做:

db.getCollection("releasesCollection").
          find({ "ReleaseDetails" : 
                 { "$elemMatch" : 
                      { "ArtistName" : {$regex:"^David"},
                        "Type" : {$regex:".*singer.*"}}})

问题是,如果我在这样的查询上调用explain(),我可以看到我在

上做的索引 实际上没有考虑

ReleaseDetails.ArtistNameReleaseDetails.Type(查询只是遍历集合中的所有文档)。

另一方面,如果我执行完全相同的查询,但用实际值替换正则表达式,换句话说,如果我这样做:

db.getCollection("releasesCollection").
          find({ "ReleaseDetails" : 
                 { "$elemMatch" : 
                      { "ArtistName" : "David Halliday",
                        "Type" : "mainSinger"}}})

在这种情况下,索引被考虑在内(explain()显示清楚)。

我的问题是,有没有办法让$ elemMatch WITH regex的查询利用索引?

(我问,因为我已经看到了,实际上,如果你对基本字段(如文本字段,而不是嵌入数组字段)进行正则表达式查询并且该字段已编入索引,我的正则表达式查询将事实上利用索引。为什么基本索引字段上的正则表达式查询使用索引但嵌入式数组索引字段上的正则表达式查询无法使用索引?)

1 个答案:

答案 0 :(得分:3)

您可能错过的两件重要事情:

1.只有区分大小写的前缀regexp可以使用mongodb中的索引,其他所有 - 不能。

例如,以下查询将使用index:

db.users.find({ "name": /^andrew/ })

2.任何查询每个查询只能使用一个索引,因此最好为查询创建复合索引:

db.items.ensureIndex({"ReleaseDetails.ArtistName": 1, "ReleaseDetails.Type" : 1});

要利用mongodb索引,您不应该使用 like regexp - > "Type" : {$regex:".*singer.*"}(可能是因为这个正则表达式,您的查询不使用索引)。

如果您真的需要 like 搜索,您可以将自己标记为Type并将其存储为数组。例如:

如果您有以下类型:“我最喜欢的歌手”,您可以:

  1. 将此词组拆分为单词并以小写形式存储:[my, favorite, singer]
  2. 使用 like 搜索这样大于3个字符的单词: [my, fav, favo, favor, favori, favorit, favorite, avorite, vorite, orite, rite, ite, avorit, vori](我已经跳过了歌手的单词标记)
  3. 完成此类标记后,您可以按完全匹配进行搜索,您的查询将使用索引,但您的数据库肯定会更大;)。
  4. 关于如何标记您可以从全文搜索引擎中读取的字词的算法,例如lucenesphinx