当前位置:   article > 正文

Mongodb $text详解

Mongodb $text详解

在建立文本索引的集合中,使用$text,mongodb能够支持文本检索。本文结合mongodb官方文档详细描述$text的定义,用法,注意事项并实践官网给出的应用举例。

定义

$text在包含文本索引字段的集合中,执行文本检索。

语法

  1. {
  2. $text: {
  3. $search: <string>,
  4. $language: <string>,
  5. $caseSensitive: <boolean>,
  6. $diacriticSensitive: <boolean>
  7. }
  8. }

其中,进行文本检索时,必须在$search中指定检索关键字。其他参数都是可选参数。

  • $text定义了文本检索的方法
  • $search是字符串类型的参数,定义文本检索关键字
  • $language设置查询时用到的语言,不同的语言单词和词汇的切分可能有差异。默认使用逗号,句号,空格等标点符号进行词汇切分。 但mongodb的文本检索,不支持中文。
  • $caseSensitive, 布尔类型的变量。定义文本检索是否大小写敏感。
  • $diacriticSensitie, 布尔类型的变量。定义文本检索是否对变音词敏感。

结合mongodb官网给出的语法,给出在查询方法中文本检索的方法。

  1. db.collection.find({
  2. $text: {
  3. $search: <string>,
  4. $language: <string>,
  5. $caseSensitive: <boolean>,
  6. $diacriticSensitive: <boolean>
  7. }
  8. })

聚合操作中,需要将文本检索放到match方法

  1. db.collection
  2. .aggregate()
  3. .match({
  4. $text: {
  5. $search: <string>,
  6. $language: <string>,
  7. $caseSensitive: <boolean>,
  8. $diacriticSensitive: <boolean>
  9. }
  10. })

使用限制

使用mongodb进行文本检索时,有下面的限制

  • 每个查询语句中,最多只能定义一个$text表达式
  • $text查询不能出现在$nor表达式, $elemMatch查询表达式和$elemMatch投射中
  • 在$or表达式中使用$text进行文本检索时,$or表达式中所有的查询条件都要有索引。
  • 使用$text查询时,不可以使用hint指定查询时用到的索引。
  • 包含$text表达式的查询中,不能使用$natural排序
  • 不能够将文本检索与其他需要特殊索引的查询结合使用。如不可以将$text和$near操作符结合使用。
  • 视图中,不支持$text进行文本检索。
  • $text不支持使用mongodb API 创建索引。

在聚合操作中,使用$text, 有额外的限制。

  • $text表达式必须在match第一个查询条件,并且只能出现一次
  • $text表达式,不能出现在$or或者$nor表达式中
  • 文本检索结果中,默认不是按照匹配分数排列。如果需要使用匹配分数排列,需要$meta获取分数,并指定排列顺序。

$search字段

用户可以在$search字段后定义查询关键字。mongodb的$text文本检索中,more会将逗号,句号,空格等标点符号作为分词符,除了减号('-')和转移的双引号(\")。

查询关键字

在$search字段中,用户添加的查询关键字,默认会使用标点符号和空格拆分开,按照单个词语进行$or查询。如果使用用户输入的整个关键字作为查询条件,需要使用转义的双引号将查询关键字包起来。如

"\"ssl certificate\""

当没有\"时,会按照ssl和certificate两个关键字,单独查询。

当用户期望查询中只对部分字段进行自动分词时,用户可以将不需要分词的部分,使用\"包围起来。

如下面的查询条件中,ssl certificate整体做为一个查询关键字, authority, key作为单独的关键字进行查询。

"\"ssl certificate\" authority key"

排除关键字

在$search中使用减号(-),用户可以定义查询返回不包含关键字的结果。

下面的语句中,在关键字coffee前添加了减号,则表示查询出包含java或shop,但不包含coffee的文档数据。

db.stores.find({$text: {$search: "java shop -coffee"}})

排除关键字使用时,有下面两个注意事项

  • 在$search字段中,只使用减号排除字段时,文本检索不会返回任何文档
  • 在单词中的减号,不会被用作排除关键字,但会被看做分隔符号。使用减号排除关键字时,需要在减号前添加空格。

文字匹配

停止单词

在英语中,助词the,连词and等词语,在按照句子成分拆分时,会被看做拆分的符号。在mongodb文本检索中,并不会按照这样的成分进行拆分,只是按照标点符号进行简单的拆分。

词干

在大小写和注音符号不敏感的文本检索中,$text操作符匹配完整的单词。所以当一个文档中包含字段值blueberry, 使用blue作为关键字检索时,并不会返回该文档。 但使用blueberry 或blueberries会匹配出该文档。

在大小写敏感的查询中,后缀词干包含大写字母时,文本检索需要精确匹配。

在注音符号敏感的查询中,后缀词干包含注音符号或标记时,文本检索需要精确匹配。

字母敏感查询

文本检索中,指定$caseSensitive: true, mongodb匹配过程中会检查字段的字母大小写。大小写与查询关键词一致的文档才会被返回。

字母敏感查询执行顺序

当用户在文本检索中,指定大小写敏感时,即$caseSensitive: true时, 文本检索会分成下面两个过程执行。

  1. 按照用户指定的关键字,进行没有大小写敏感和注音符号的文本查询
  2. 在返回的文档当中,按照用户指定的关键字字母大小写顺序,过滤到不符合的文档。

由此可以看出,当用户指定大小写敏感时,mongodb将文本检索分成了两个过程。所以这种查询会对查询的性能产生影响。

注音符号敏感查询

与大小写敏感类似,当用户指定注音符号敏感时,mongodb的文本检索也分为了两个过程。先按照不敏感的关键字查询出结果,然后在过滤掉不符合用户关键字中注音的文档。当然,注音符号敏感也会影响mongodb文本检索的性能。

文本匹配评分

使用$text做文本检索时。mongodb会为集合中的文档文字索引计算出与查询关联词中的相关性评分。使用{$meta: "textScore"},可以获得这个评分信息。

应用举例

创建集合articles, 并添加文本索引

  1. db.articles.createIndex({subject: "text"})
  2. db.articles.insertMany([
  3. { _id: 1, subject: "coffee", author: "xyz", views: 50 },
  4. { _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
  5. { _id: 3, subject: "Baking a cake", author: "abc", views: 90 },
  6. { _id: 4, subject: "baking", author: "xyz", views: 100 },
  7. { _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
  8. { _id: 6, subject: "Сырники", author: "jkl", views: 80 },
  9. { _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
  10. { _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
  11. ])

单个单词查询

db.articles.find({$text: {$search: "coffee"}})

匹配多个单词,mongodb默认使用空格,逗号等将用户输入的"bake coffee cake"拆分成3个关键字并进行or查询,匹配到任意一个关键字的文档都会被查询出来

db.articles.find({$text: {$search: "bake coffee cake"}})

使用转义双引号\",匹配带有标点符号和空格的查询关键字。使用转义双引号将关键字包围起来,mongodb不会对查询关键字进行拆分,而是作为整体去查询。

db.articles.find({$text: {$search: "\"coffee shop\""}})

使用转义的单引号,mongodb还是对查询关键字进行拆分。两个查询返回结果一致

  1. db.articles.find({$text: {$search: "\'coffee shop\' \'cafe con Leche\'"}})
  2. db.articles.find({$text: {$search: "coffee shop cafe con Leche"}})

使用减号,排除关键字

db.articles.find({$text: {$search: "coffee -shop"}})

指定文本检索时使用的语言

db.articles.find({$text: {$search: "leche", $language: "es"}})

使用带有注音标记符的关键字查询

db.articles.find({$text: {$search: "сы́рники CAFÉS"}})

大小写敏感查询

  1. db.articles.find({$text: {$search: "Coffee", $caseSensitive: true}})
  2. db.articles.find({$text: {$search: "\"Café Con Leche\"", $caseSensitive: true}})
  3. db.articles.find({$text: {$search: "Coffee -shop", $caseSensitive: true}})

注音标记符敏感查询

  1. db.articles.find( { $text: { $search: "CAFÉ", $diacriticSensitive: true } } )
  2. db.articles.find(
  3. { $text: { $search: "leches -cafés", $diacriticSensitive: true } }
  4. )

获取mongodb计算的相似度

  1. db.articles.find(
  2. { $text: {$search: "cake"}},
  3. { score: {$meta: "textScore"}}
  4. )

按照相似度排序,排序是,score字段名称可以是任意合法名称

  1. db.articles.find(
  2. { $text: {$search: "coffee"}},
  3. { score: {$meta: "textScore"}}
  4. ).sort({ score: {$meta: "textScore"}})

按照相似度排序并限制返回数量

  1. db.articles.find(
  2. { $text: {$search: "coffee"}},
  3. { score: {$meta: "textScore"}}
  4. ).sort({ score: {$meta: "textScore"}})
  5. .limit(2)

添加其他查询条件

  1. db.articles.find(
  2. {author: 'xyz', $text: {$search: "coffee"}},
  3. { score: {$meta: "textScore"}}
  4. ).sort({date: 1, score: {$meta: "textScore"}})
  5. .limit(2)

聚合操作中使用文本检索

  1. db.articles.aggregate(
  2. [
  3. {$match: {$text: { $search: "cake tea"}}},
  4. {$sort: { score: {$meta:"textScore"}}},
  5. {$project: {subject: 1, _id: 0}}
  6. ]
  7. )
  8. db.articles.aggregate(
  9. [
  10. {$match: {$text: { $search: "cake tea"}}},
  11. {$project: {subject: 1, _id: 0, score: { $meta: "textScore"}}},
  12. {$match: {score: {$gt: 0.7}}}
  13. ]
  14. )
  15. db.articles.aggregate(
  16. [
  17. {$match: {$text: { $search: "cake tea", $language: 'es'}}},
  18. {$project: {subject: 1, _id: 0, score: { $meta: "textScore"}}},
  19. {$match: {score: {$gt: 0.7}}}
  20. ]
  21. )

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/140842
推荐阅读
相关标签
  

闽ICP备14008679号