MongoDB - 文本字段索引和文本索引之间的区别?

Posted

技术标签:

【中文标题】MongoDB - 文本字段索引和文本索引之间的区别?【英文标题】:MongoDB - Difference between index on text field and text index? 【发布时间】:2014-08-10 13:16:45 【问题描述】:

对于包含字符串(例如,州或省名称)的 MongoDB 字段,在字符串类型字段上创建索引之间有什么(如果有)区别:

db.ensureIndex(  field: 1  )

并在该字段上创建文本索引:

db.ensureIndex(  field: "text" 

在这两种情况下,field 都是 string 类型。

我正在寻找一种方法来对包含单个单词(可能更多)的文本字段进行不区分大小写的搜索。作为 Mongo 的新手,我无法区分使用上述两种索引方法,甚至是 $regex 搜索。

【问题讨论】:

深入到 1 行:一个为 FTS 技术提供动力,另一个是查找查询的普通索引。 我还没有实现它,但case insensitive indexes 似乎是您正在寻找的解决方案!我现在想提一下,以防我忘记回来写答案。 不区分大小写的索引在 mongodb 3.4 中是新的(不幸的是我没有使用它)。 【参考方案1】:

这两个索引选项非常不同。

当您在字符串字段上创建常规索引时,它会索引 字符串中的整个值。对单个单词字符串最有用 (如登录用户名)您可以完全匹配的位置。

另一方面,文本索引将标记并阻止 场。所以它会将字符串分解为单个单词或 标记,并将进一步将它们简化为它们的词干,以便变体 相同单词的匹配(“talk”匹配“talks”、“talked”和 例如“talking”,因为“talk”是所有三个词的词干)。大多 对于真正的文本(句子、段落等)很有用。

文本搜索

文本搜索支持在一个文档中搜索字符串内容 收藏。 MongoDB 提供$text 运算符来执行文本搜索 在查询和聚合管道中。

文本搜索过程:

tokenizes and stems the search term(s) during both the index creation and the text command execution.
assigns a score to each document that contains the search term in the indexed fields. The score determines the relevance of a document to a given search query.

$text 运算符可以搜索单词和短语。查询匹配 在完整的词干上。例如,如果一个文档字段 包含词 blueberry,搜索词 blue 将不匹配 文件。但是,搜索蓝莓或蓝莓 将匹配。

$regex 搜索可以与字符串字段的常规索引一起使用,以 提供一些模式匹配和通配符搜索。不是很糟糕 索引的有效用户,但它会尽可能使用索引:

如果字段存在索引,则 MongoDB 匹配正则 针对索引中的值的表达式,这可能比 收藏扫描。如果常规的可以进一步优化 表达式是一个“前缀表达式”,这意味着所有潜在的 匹配以相同的字符串开头。这允许 MongoDB 构建一个 来自该前缀的“范围”,并且仅匹配来自该前缀的那些值 范围内的索引。

http://docs.mongodb.org/manual/core/index-text/

http://docs.mongodb.org/manual/reference/operator/query/regex/

【讨论】:

这很好,很清楚,谢谢!在包含单个单词的字段上进行不区分大小写搜索的最佳方法是什么?听起来$regex 或文本索引都可以。 $regex 搜索是否使用了常规索引? 根据上面链接的the mongodb regex documentation:对于不区分大小写的正则表达式查询,这些查询一般不能有效地使用索引。 您好,我想对上述两种类型的索引有疑问。当有 2 个查询时,我应该使用哪一个,其中一个是 = name,另一个是在用户名上遵循正则表达式?【参考方案2】:

文本索引允许您在文本中搜索单词。您可以在非文本索引文本字段上使用正则表达式执行相同操作,但速度会慢得多。

在 MongoDB 2.6 之前,文本搜索操作必须使用自己的命令进行,这是一个很大的缺点,因为您无法将其与其他过滤器组合,也无法将结果视为通用游标。到目前为止,文本搜索只是典型 find 方法的另一个运算符,这非常好。

那么,为什么文本索引及其后续搜索比非索引文本字段上的正则表达式更快?这是因为文本索引就像字典一样工作,这是一个聪明的字典,能够在每种语言的基础上丢弃单词(默认为英语)。当您运行文本搜索查询时,您可以针对字典运行它,从而节省了用于迭代整个集合的时间。

请记住,文本索引会随着您的收藏而增长,并且会占用大量空间。在使用上限集合时,我很难学到这一点。没有办法限制文本索引。

文本字段上的常规索引,例如

db.ensureIndex(  field: 1  )

仅当您搜索整个文本时才有用。例如,它用于查找字母数字哈希。在存储文本段落、短语等时应用这种索引没有任何意义。

【讨论】:

感谢您的回复!您提到文本索引比非索引文本字段上的正则表达式更快。 (普通)索引文本字段(仅包含 1 个单词)上的正则表达式怎么样?将文本索引添加到仅包含 1 个单词的字段(用于精确、不区分大小写的匹配)是否有任何好处? 对于精确匹配,无论是区分大小写还是不区分大小写,都没有使用文本索引。但就此而言,您也不需要使用正则表达式。请记住,文本索引保留了一个单词字典(用空格扩展文本并丢弃常用词和特殊字符),而正则表达式匹配可以包括空格、引号、冒号等的子字符串模式。 嗯好吧,那么我如何在不使用正则表达式的情况下执行不区分大小写的精确匹配?普通索引创建的哈希不会受大小写影响吗? @russdot 你找到答案了吗?根据regex documentation,对于不区分大小写的正则表达式查询,这些查询一般不能有效地使用索引。不知道没有正则表达式或文本索引你会怎么做。 我终于偶然发现了case insensitive indexes!每个人都在不断输入文本索引,所以很难找到...

以上是关于MongoDB - 文本字段索引和文本索引之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB:带有数组的文本索引,只有第一个词被索引

MongoDB索引问题

Ruby操作MongoDB(进阶十)--文本搜索text search

MongoDB 索引文本搜索仅适用于完全匹配

MongoDB 学习笔记之 TTL索引,部分索引和文本索引

mongodb文本搜索