MongoDB 全文索引

什么是全文索引?

MongoDB 中,全文索引(Full-Text Index)是一种用于支持全文搜索的索引类型。它可以用于在文本数据中执行高效的文本搜索和匹配操作。

全文检索对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。

这个过程类似于通过字典中的检索字表查字的过程。

MongoDB 从 2.4 版本开始支持全文检索,目前支持15种语言的全文索引。

  • danish

  • dutch

  • english

  • finnish

  • french

  • german

  • hungarian

  • italian

  • norwegian

  • portuguese

  • romanian

  • russian

  • spanish

  • swedish

  • turkish

启用全文索引

MongoDB 在 2.6 版本以后是默认开启全文索引的,如果你使用之前的版本,你需要使用以下代码来启用全文索引:

db.adminCommand({ setParameter:true, textSearchEnabled:true })

或者使用命令:

mongod --setParameter textSearchEnabled=true

创建全文索引

要在 MongoDB 中创建全文索引,需要使用 text 索引类型。可以在集合上使用 createIndex() 方法创建全文索引,指定要索引的字段和索引的类型。例如:

# col 集合数据如下
> db.col.find()
{ "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 3, "email" : "zhangsan@outlook.com", "sex" : "male" }
{ "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com lis@163.com ls@gmail.com", "sex" : "female" }
{ "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 27, "email" : "wangwu@sina.com.cn", "sex" : "male" }
{ "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 22, "email" : "zhaoliu@gmail.com", "sex" : "female" }
{ "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com guq@163.com", "sex" : "male" }
{ "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" }

# 在 col 的 email 字段上创建全文索引
> db.col.createIndex({ email:"text" })
{
       "numIndexesBefore" : 2,
       "numIndexesAfter" : 3,
       "createdCollectionAutomatically" : false,
       "ok" : 1
}

在上面的示例中,name 是要创建全文索引的字段。

执行全文搜索

一旦创建了全文索引,就可以使用 $text 操作符进行全文搜索。可以在查询中使用 $text 操作符,指定要搜索的关键词。例如:

> db.col.find({ $text:{$search:"163"} })
{ "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com guq@163.com", "sex" : "male" }
{ "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com lis@163.com ls@gmail.com", "sex" : "female" }

上面例子中,163 是要搜索的关键词。

删除全文索引

删除已存在的全文索引,可以使用 getIndexes() 命令获取所有的索引信息,例如:

> db.col.getIndexes()
[
       {
               "v" : 2,
               "key" : {
                       "_id" : 1
               },
               "name" : "_id_"
       },
       {
               "v" : 2,
               "key" : {
                       "name" : 1,
                       "age" : 1
               },
               "name" : "name_1_age_1"
       },
       {
               "v" : 2,
               "key" : {
                       "_fts" : "text",
                       "_ftsx" : 1
               },
               "name" : "email_text",
               "weights" : {
                       "email" : 1
               },
               "default_language" : "english",
               "language_override" : "language",
               "textIndexVersion" : 3
       }
]

上面命令的输出中,名为 “email_text” 的就是刚刚创建的全文索引。然后,通过索引名 email_text,执行以下命令来删除索引:

> db.col.dropIndex("email_text")
{ "nIndexesWas" : 3, "ok" : 1 }

通配符全文索引

在多个字段上创建文本索引时,还可以使用通配符说明符 $**。使用通配符文本索引,MongoDB 会为包含集合中每个文档的字符串数据的每个字段编制索引。以下示例使用通配符说明符创建文本索引:

# 创建通配符全文索引
> db.col.createIndex( { "$**": "text" } )
{
       "numIndexesBefore" : 1,
       "numIndexesAfter" : 2,
       "createdCollectionAutomatically" : false,
       "ok" : 1
}

# 下面例子证明了在 name 和 email 上面均存在全文索引
> db.col.find({ $text:{$search:"sina"} })
{ "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 27, "email" : "wangwu@sina.com.cn", "sex" : "male" }
> db.col.find({ $text:{$search:"张三"} })
{ "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 3, "email" : "zhangsan@outlook.com", "sex" : "male" }

此索引允许在包含字符串内容的所有字段上进行文本搜索。如果不清楚要包含在文本索引中的哪些字段或用于临时查询,则此类索引对于高度非结构化数据可能很有用。

通配符文本索引是多个字段上的文本索引。因此,您可以在创建索引期间为特定字段指定权重,以控制结果的排名。有关使用权重控制文本搜索结果的更多信息,请参阅使用权重控制搜索结果。

与所有文本索引一样,通配符文本索引可以是复合索引的一部分。 例如,以下内容在字段a和通配符说明符上创建复合索引:

db.col.createIndex( { a: 1, "$**": "text" } )

与所有复合文本索引一样,由于 a 位于文本索引键之前,因此为了使用此索引执行 $text 搜索,查询谓词必须包含 a 的相等匹配条件。

稀疏属性 (sparse Property)

文本索引总是稀疏的,并忽略稀疏选项。如果文档缺少文本索引字段(或者字段为null或空数组),则 MongoDB 不会将文档条目添加到文本索引中。对于插入,MongoDB 插入文档但不添加到文本索引。

对于包含文本索引键和其他类型键的复合索引,只有文本索引字段确定索引是否引用文档。其他键不确定索引是否引用文档。

全文索引的限制

MongoDB 全文索引有一些限制和特性,其中包括:

  • 默认情况下,全文索引不会包括短词(少于三个字符)和常见词(停用词)。

  • 全文索引使用自然语言文本搜索,支持词根和词形的搜索。

  • 一个集合最多可以有一个文本索引。

  • 文本搜索和提示,如果查询包含 $text 查询表达式,则不能使用hint()。

  • 文本索引和排序,排序操作无法从文本索引获取排序顺序,即使是复合文本索引也是如此。即排序操作不能使用文本索引中的排序。

  • 复合索引,复合索引可以包括文本索引键与升序/降序索引键的组合。但是,这些复合索引具有以下限制:

    • 复合文本索引不能包含任何其他特殊索引类型,例如多键或地理空间索引字段。

    • 如果复合文本索引包括文本索引键之前的键,则执行 $text 搜索时,查询谓词必须包含前面键上的相等匹配条件。

    • 创建复合文本索引时,必须在索引规范文档中相邻地列出所有文本索引键。

高级全文搜索

ngoDB 还提供了一些高级功能来支持更复杂的全文搜索需求,包括:

  • 使用 $language 操作符指定搜索的语言。

  • 使用 $caseSensitive 操作符指定搜索是否区分大小写。

  • 使用 $diacriticSensitive 操作符指定搜索是否区分重音符号。

例如:

> db.col.find({ $text: { $search: "sina", $language: "en", $caseSensitive: true } });
{ "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 27, "email" : "wangwu@sina.com.cn", "sex" : "male" }

在上面的示例中,$language 操作符指定了搜索的语言为英语,$caseSensitive 操作符指定了搜索区分大小写。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号