regex字段上的mongodb索引不起作用



我是mongoDB的新手,我面临着一个需要您帮助的性能问题。我有一个有400k条记录的集合,当不为集合上的任何字段创建索引时,每个查询需要20-30秒,然后我为通常用于搜索查询的字段创建索引,但问题是,当使用$regex搜索带有索引的字符串字段时,mongoDB不在该字段上使用索引,mongoDB仍然扫描该集合中的所有记录,我在网上搜索过这个关键词:;regex字段mongodb上的索引";我找到了一些答案,上面写着";MongoDB使用RegEx前缀查找索引";这意味着你必须使用"^"索引的前缀类似于";db.users.find({name:/^关键字/}(";,但这对我不起作用,是吗;$regex字段上的索引";需要MongoDB Atlas工作吗?因为我使用的是mongoDB的comunity版本。谢谢

这里有很多东西需要打开包装。我们将把答案分为两部分,第一部分尝试回答一些关于索引使用的直接问题,第二部分探索满足应用程序需求的解决方案。

$regex的索引用法

与任何数据库中捕获完整字符串值作为关键字的索引一样,MongoDB可以将索引用于$regex操作,但其效率在很大程度上取决于所应用的正则表达式。这就是您引用的评论和其他答案中的索引使用文档所描述的内容。

在注释中,您提到一个示例查询可能是db.users.find({name: {$regex: '.*keyword.*', $options: 'i'}})。这意味着regex是一个既不固定又不区分大小写的正则表达式。上述冲洗状态直接为:

不区分大小写的正则表达式查询通常无法有效使用索引。

为什么会这样?因为您正在搜索的子字符串可以在索引捕获的任何字符串值中找到。因此,具有匹配值{name: 'a keyword'}的文档将位于索引的一端,{name: 'keyWord' }可能位于中间的某个位置,而{name: 'Z keyword'}可能位于结尾。确保结果正确的唯一方法是数据库扫描索引中的所有字符串值。因此,尽管它仍在使用索引,但它可能效率不高,因为大多数扫描的值将不匹配,并将被丢弃。

您可以始终使用.explain()来更好地了解数据库是如何回答查询的,例如是否以及如何使用索引。

解决方案

那么我们该怎么办呢?

正如@rickhg12hs在评论中所建议的那样,这取决于你想要实现的目标。您重申,您正在寻找">完整的regex搜索功能",但这实际上是一种方法/解决方案,而不是目标。例如,如果您真正需要的只是以不区分大小写的方式匹配一个精确的字符串,那么像不区分大小字母的索引这样简单的东西可能会起到作用。

然而,如果真的希望执行任意子字符串搜索,那么您实际上是在考虑搜索引擎的功能。在这种情况下,你最好的选择可能是直接在MongoDB中模拟他们的索引(例如,让应用程序手动标记要索引的字符串(,在MongoDB旁边建立Solr/Elasticsearch之类的东西,或者使用MongoDB的Atlas Search产品。注释中提到的$text运算符在子字符串搜索(例如仅搜索单词的一部分(方面有局限性,这可能与您的需求相关,也可能与您不相关。

最新更新