24.MongoDB文本索引

24.MongoDB文本索引


24.1 知识点

MongoDB 文本索引概述

MongoDB 的文本索引 (Text Index) 是一种特殊类型的索引,它允许我们对字符串类型的字段进行全文搜索。通过创建文本索引,MongoDB 可以在大量文本数据中执行高效的文本搜索操作。这个特性特别适用于需要对大量文本数据进行查询的场景,如博客、文章、评论等内容管理系统。

语法

文本索引允许在一个或多个字段上创建索引,支持对这些字段进行全文搜索。你可以通过 createIndex 方法来创建文本索引。下面是创建文本索引的基本示例

// 单字段索引
db.collection.createIndex({ title: "text" })
// 复合索引
db.collection.createIndex({ title: "text", content: "text" })

这条命令会在 articles 集合中的 titlecontent 字段上创建一个复合文本索引,意味着你可以对这两个字段进行全文搜索。

特性

  • 支持多个字段: 一个文本索引可以跨多个字段。例如,如果文章有标题 (title) 和内容 (content),你可以同时对这两个字段创建文本索引。
  • 大小写不敏感: MongoDB 会将文本字段的所有内容转化为小写,这意味着搜索是大小写不敏感的。
  • 分词: MongoDB 会自动根据空格和标点符号来分词,并为每个词建立索引。
  • 支持停用词: 一些常见的“无意义”词汇(如“the”、“a”、“and”等)会被忽略,除非你显式配置文本索引来使用这些词。
  • 多语言支持: MongoDB 提供了多种语言的分词器(如英语、中文、法语等)。

自定义停用词(针对非英文语言)

如果你想为其他语言或特定需求自定义停用词集合,MongoDB 提供了选项来指定使用不同的分词器或自定义停用词列表。 MongoDB 通过 default_language 参数来指定语言,而通过 language_override 来让 MongoDB 根据特定字段的语言动态选择停用词。

设置语言

MongoDB 支持多种语言的分词器(包括中文、法语、德语等)。默认情况下,MongoDB 使用英语分词器,你可以通过在创建索引时显式指定语言来更改这一行为。

例如,设置为法语:

db.collection.createIndex(
  { title: "text", content: "text" },
  { default_language: "fr" }
)

MongoDB 支持多种语言,以下是你可以使用的语言代码:

  1. 阿拉伯语ar
  2. 保加利亚语bg
  3. 简体中文zh
  4. 繁体中文zh-Hant
  5. 捷克语cs
  6. 丹麦语da
  7. 荷兰语nl
  8. 英语en
  9. 爱沙尼亚语et
  10. 芬兰语fi
  11. 法语fr
  12. 德语de
  13. 希腊语el
  14. 希伯来语he
  15. 匈牙利语hu
  16. 意大利语it
  17. 日语ja
  18. 韩语ko
  19. 拉脱维亚语lv
  20. 立陶宛语lt
  21. 挪威语no
  22. 波兰语pl
  23. 葡萄牙语pt
  24. 罗马尼亚语ro
  25. 俄语ru
  26. 西班牙语es
  27. 瑞典语sv
  28. 泰语th
  29. 土耳其语tr
  30. 乌克兰语uk

使用自定义语言(禁用默认的语言分词器)

MongoDB 默认使用的分词器会自动应用默认语言的停用词集合(例如,英语)。虽然 MongoDB 不允许直接禁用停用词,但你可以选择一种分词器,它可能不会使用停用词,或者选择一个没有停用词的语言分词器。

通过 default_language 参数控制语言:你可以为文本索引指定不同的分词器,或指定一种没有停用词的语言。比如,使用 none 或者 simple 语言,这些语言的分词器不会应用停用词。

db.collection.createIndex(
  { title: "text", content: "text" },
  { default_language: "none" }
);

这种设置指定了 none 语言分词器,这会避免使用任何语言的默认停用词。

none 语言分词器none 是 MongoDB 提供的一种简单的分词器,它不会进行任何语言特定的分词,也不会有停用词过滤。

simple 语言分词器simple 是另一个常见的分词器,它会去除一些最常见的停用词,但比默认的分词器过滤得更少。

db.collection.createIndex(
  { title: "text", content: "text" },
  { default_language: "simple" }
);

language_override

language_override 选项用于指定文档的某个字段来覆盖默认的语言设置。默认情况下,MongoDB 会根据 default_language 参数使用某种语言(通常是英语),来处理文本分析(如分词、停用词、词干提取等)。如果你的文档中包含多个语言的文本数据,或者文档中的某些字段需要特别的语言设置,你可以通过 language_override 来指定一个字段,覆盖默认语言。

db.collection.createIndex(
   { field: "text" }, 
   { 
     default_language: "english", 
     language_override: "lang_field" 
   }
)
  • default_language: 这是一个可选参数,用于设置默认语言(如果没有显式指定)。
  • language_override: 这是你要指定的字段名称,MongoDB 会根据该字段的值来选择特定的语言。如果文档没有该字段,MongoDB 会使用 default_language
{
   "_id": 1,
   "title": "Hello World",
   "content": "This is a test document in English",
   "lang_field": "english"
}

{
   "_id": 2,
   "title": "Hola Mundo",
   "content": "Este es un documento de prueba en español",
   "lang_field": "spanish"
}

在这种情况下,你可以通过 language_override 来指定 lang_field 字段来覆盖每个文档的默认语言。

db.collection.createIndex(
   { content: "text" },
   {
      default_language: "english",
      language_override: "lang_field"
   }
)

这样,content 字段将根据每个文档中的 lang_field 值来选择正确的语言:

  • 对于第一篇文档,lang_field 的值是 "english",所以会按照英语处理文本。
  • 对于第二篇文档,lang_field 的值是 "spanish",所以会按照西班牙语处理文本。

使用场景

创建了文本索引之后,你可以使用 $text 查询运算符来执行全文搜索。

简单查询

假设你创建了一个包含标题 (title) 和内容 (content) 字段的文本索引,你可以使用 $text 运算符来搜索某个词汇或短语:

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

这会搜索 titlecontent 字段中包含 “MongoDB” 这个词的文档。

短语搜索

你也可以搜索多个词汇组成的短语,只需要将词组放在双引号中:

db.articles.find({ $text: { $search: "\"MongoDB Indexing\"" } })

排除某些词汇

你可以通过在词汇前加上减号(-)来排除某些词汇。比如,我们要搜索包含 “MongoDB” 但不包含 “performance” 的文章:

db.articles.find({ $text: { $search: "MongoDB -performance" } })

权重

MongoDB 允许为文本索引中的字段分配权重,从而控制不同字段在搜索结果中的重要性。例如,如果你认为文章的 title 字段比 content 字段更重要,可以设置权重:

db.articles.createIndex(
  { title: "text", content: "text" },
  { weights: { title: 10, content: 5 } }
)

在这个例子中,title 字段的权重是 10,而 content 字段的权重是 5。在搜索时,匹配到 title 的文档会被认为更相关,从而提高其排名。

文本搜索的额外操作

MongoDB 可以返回匹配的文本字段的相关性得分。这个得分基于匹配度,越高的得分表示越相关的结果。你可以使用 $meta 运算符来获取这些得分。

db.articles.find(
  { $text: { $search: "MongoDB" } },
  { score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })

删除文本索引

如果你不再需要某个文本索引,可以通过 dropIndex 删除它:

db.articles.dropIndex("title_text_content_text")

这里的 "title_text_content_text" 是自动生成的索引名称,通常由字段名和索引类型组成。

示例

假设你在开发一个博客系统,想要为文章的标题和内容添加全文搜索功能。

准备数据

db.posts.insertMany([
  { title: "Introduction to MongoDB", content: "MongoDB is a NoSQL database." },
  { title: "MongoDB Indexing", content: "This article explains how to use MongoDB indexes." },
  { title: "MongoDB for Beginners", content: "Learn MongoDB basics in this tutorial." },
  { title: "Advanced MongoDB Features", content: "Explore advanced features like sharding and replication." }
])

创建文本索引

db.posts.createIndex({ title: "text", content: "text" })

执行文本搜索

搜索 “MongoDB”:

db.posts.find({ $text: { $search: "MongoDB" } })

搜索 “NoSQL” 并按相关性排序:

db.posts.find({ $text: { $search: "NoSQL" } })
  .sort({ score: { $meta: "textScore" } })

排除某个词汇,搜索 “MongoDB” 但不包含 “tutorial”:

db.posts.find({ $text: { $search: "MongoDB -tutorial" } })

注意事项

  • 文本索引的大小: 文本索引可能占用大量存储空间,尤其是在字段内容较长的情况下。要确保在创建文本索引时合理管理数据。
  • 分词语言: MongoDB 选择分词器时默认是英语。对于多语言环境,你可能需要调整分词器来支持其他语言。
  • 性能: 在数据量较大时,创建和维护文本索引可能影响写入性能。建议根据实际需求合理使用。

总结

MongoDB 的文本索引提供了一种高效的方式来执行全文搜索,可以对多个字段进行索引,支持复杂的查询操作如短语匹配、排除词汇、返回相关性得分等。合理利用文本索引,可以大大提升基于文本数据的搜索效率。



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏