24.MongoDB文本索引
24.1 知识点
MongoDB 文本索引概述
MongoDB 的文本索引 (Text Index) 是一种特殊类型的索引,它允许我们对字符串类型的字段进行全文搜索。通过创建文本索引,MongoDB 可以在大量文本数据中执行高效的文本搜索操作。这个特性特别适用于需要对大量文本数据进行查询的场景,如博客、文章、评论等内容管理系统。
语法
文本索引允许在一个或多个字段上创建索引,支持对这些字段进行全文搜索。你可以通过 createIndex
方法来创建文本索引。下面是创建文本索引的基本示例
// 单字段索引
db.collection.createIndex({ title: "text" })
// 复合索引
db.collection.createIndex({ title: "text", content: "text" })
这条命令会在 articles
集合中的 title
和 content
字段上创建一个复合文本索引,意味着你可以对这两个字段进行全文搜索。
特性
- 支持多个字段: 一个文本索引可以跨多个字段。例如,如果文章有标题 (
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 支持多种语言,以下是你可以使用的语言代码:
- 阿拉伯语:
ar
- 保加利亚语:
bg
- 简体中文:
zh
- 繁体中文:
zh-Hant
- 捷克语:
cs
- 丹麦语:
da
- 荷兰语:
nl
- 英语:
en
- 爱沙尼亚语:
et
- 芬兰语:
fi
- 法语:
fr
- 德语:
de
- 希腊语:
el
- 希伯来语:
he
- 匈牙利语:
hu
- 意大利语:
it
- 日语:
ja
- 韩语:
ko
- 拉脱维亚语:
lv
- 立陶宛语:
lt
- 挪威语:
no
- 波兰语:
pl
- 葡萄牙语:
pt
- 罗马尼亚语:
ro
- 俄语:
ru
- 西班牙语:
es
- 瑞典语:
sv
- 泰语:
th
- 土耳其语:
tr
- 乌克兰语:
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" } })
这会搜索 title
和 content
字段中包含 “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