MongoDB,通过正则表达式对索引字段的查询性能
Posted
技术标签:
【中文标题】MongoDB,通过正则表达式对索引字段的查询性能【英文标题】:MongoDB, performance of query by regular expression on indexed fields 【发布时间】:2013-07-04 07:39:38 【问题描述】:我想按名称查找帐户(在 50K 帐户的 MongoDB 集合中)
以通常的方式:我们用字符串查找
db.accounts.find( name: 'Jon Skeet' ) // indexes help improve performance!
用正则表达式怎么样?这是一项昂贵的手术吗?
db.accounts.find( name: /Jon Skeet/ ) // worry! how indexes work with regex?
编辑:
根据 WiredPrairie:
MongoDB 使用 RegEx 的 prefix 来查找索引(例如:/^prefix.*/
):
db.accounts.find( name: /^Jon Skeet/ ) // indexes will help!'
MongoDB $regex
【问题讨论】:
@dirkk,我想获得更多的经验和解释。我也想分享这个问题。 要使正则表达式使用索引,它必须使用文档中所示的锚点:docs.mongodb.org/manual/reference/operator/regex How to query mongodb with "like"?的可能重复 *** 上已经回答了许多其他非常相似的问题。 @WiredPrairie 我想关注性能而不是如何进行查询。 【参考方案1】:其实根据文档,
如果字段存在索引,则 MongoDB 匹配正则 针对索引中的值的表达式,这可能比 收藏扫描。如果常规的可以进一步优化 表达式是一个“前缀表达式”,这意味着所有潜在的 匹配以相同的字符串开头。这允许 MongoDB 构建一个 来自该前缀的“范围”,并且仅匹配来自该前缀的那些值 范围内的索引。
http://docs.mongodb.org/manual/reference/operator/query/regex/#index-use
换句话说:
对于/Jon Skeet/
regex,mongo 会全盘扫描索引中的键,然后获取匹配的文档,这比集合扫描更快。
对于/^Jon Skeet/
正则表达式,mongo只会扫描索引中以正则表达式开头的范围,这样会更快。
【讨论】:
如果有直接匹配(即:匹配字母a
),则正则表达式可以正常工作。但是如果我匹配一个完整的单词结果需要更长的时间(即:angular
)。这是跨越 6M 文档,有没有办法加快这些查询?超过 8 个字符需要 19-30 秒,但会立即返回 1-2 个字符。
@chovy,我认为 MongoDB 不是搜索文本中间出现的字符串的最佳工具 - 我建议查看 ElasticSearch 或任何其他全文搜索引擎。【参考方案2】:
如果有人仍然对搜索性能有疑问,有一种方法可以优化正则表达式搜索,即使它在句子中搜索一个单词(不一定在字符串的开头 ^
或结尾 $
)。
该字段应该有一个文本索引
db.someCollection.createIndex( someField: "text" )
只有在先执行普通搜索后,查询才应使用正则表达式
db.someCollection.find( $and:
[
$text: $search: "someWord" ,
someField: $elemMatch: $regex: /test/ig, $regex: /other/ig
]
)
这确保了正则表达式仅针对初始的普通搜索的结果运行,由于该字段上的索引,这应该非常快。 它可能会对搜索性能产生巨大影响,具体取决于集合的大小。
【讨论】:
感谢您的意见。不过,我必须处理两个搜索条件。整个单词,然后是单词的一部分。 如果您不搜索完整的单词,这实际上不起作用。如果您按文本索引搜索,“some”将不返回任何内容。以上是关于MongoDB,通过正则表达式对索引字段的查询性能的主要内容,如果未能解决你的问题,请参考以下文章