文本搜索
概述
文本搜索允许您在集合中搜索指定单词或短语的字符串类型字段。您可以通过使用以下方式执行文本搜索:$text
运算符,它在搜索字符串中每个由空格分隔的术语上执行逻辑OR
。您还可以向运算符指定更多选项,以处理支持语言的大小写敏感性、停用词和词干(如复数形式或其他时态)。这通常用于非结构化文本,如转录、论文或网页。
$text
查询运算符要求您在集合的文本索引中指定搜索字段。请参阅下面的示例代码,以获取创建文本索引和使用$text
查询运算符的示例。
注意
Atlas Search可以帮助您在MongoDB数据上构建快速、基于相关性的搜索功能。今天就在我们的全托管数据库服务MongoDB Atlas上试用。
示例
以下示例使用了sample_mflix
数据库中movies
集合的样本数据。要启用对title
字段的文本搜索,请使用以下命令创建一个文本索引:
db.movies.createIndex({ title: "text" });
本指南中的示例使用单个字段文本索引,但您也可以创建一个复合文本索引,将您的文本查询扩展到多个字段。以下命令在movies
集合的两个字段上创建文本索引:
db.movies.createIndex({ title: "text", plot: "text" });
提示
在文本索引中指定字段权重
您可以为每个集合创建一个文本索引。每个文本搜索查询索引中指定的所有字段以进行匹配。
要了解有关文本索引的更多信息,请参阅服务器手册中的文本索引。
按单词查询
此示例通过搜索包含单词"trek"的标题来查询《星际迷航》电影。如果您想使用多个单词进行查询,请用空格分隔您的单词以查询与任何搜索术语匹配的文档(逻辑OR
)。
// Create a query that searches for the string "trek" const query = { $text: { $search: "trek" } }; // Return only the `title` of each matched document const projection = { _id: 0, title: 1, }; // Find documents based on our query and projection const cursor = movies.find(query).project(projection);
此操作返回以下文档
{ title: 'Trek Nation' } { title: 'Star Trek' } { title: 'Star Trek Into Darkness' } { title: 'Star Trek: Nemesis' } { title: 'Star Trek: Insurrection' } { title: 'Star Trek: Generations' } { title: 'Star Trek: First Contact' } { title: 'Star Trek: The Motion Picture' } { title: 'Star Trek VI: The Undiscovered Country' } { title: 'Star Trek V: The Final Frontier' } { title: 'Star Trek IV: The Voyage Home' } { title: 'Star Trek III: The Search for Spock' } { title: 'Star Trek II: The Wrath of Khan' }
成功!查询找到了movies
集合中所有包含单词"trek"标题的文档。不幸的是,搜索包含了一个意外项目:"Trek Nation",这是一部关于《星际迷航》的电影,而不是《星际迷航》电影系列的一部分。为了解决这个问题,我们可以使用更具体的短语进行查询。
按短语查询
为了使您的查询更加具体,请尝试使用"star trek"短语而不是仅使用单词"trek"。为了按短语查询,请用转义引号包围您的多词短语(\"<term>\"
)
// Create a query that searches for the phrase "star trek" const query = { $text: { $search: "\"star trek\"" } }; // Return only the `title` of each matched document const projection = { _id: 0, title: 1, }; // Find documents based on the query and projection const cursor = movies.find(query).project(projection);
与仅使用术语"trek"
相比,按短语"star trek"
查询匹配以下文档
{ title: 'Star Trek' } { title: 'Star Trek Into Darkness' } { title: 'Star Trek: Nemesis' } { title: 'Star Trek: Insurrection' } { title: 'Star Trek: Generations' } { title: 'Star Trek: First Contact' } { title: 'Star Trek: The Motion Picture' } { title: 'Star Trek VI: The Undiscovered Country' } { title: 'Star Trek V: The Final Frontier' } { title: 'Star Trek IV: The Voyage Home' } { title: 'Star Trek III: The Search for Spock' } { title: 'Star Trek II: The Wrath of Khan' }
这些结果包括数据库中包含短语"star trek"
的所有电影,在这种情况下,结果仅限于虚构的《星际迷航》电影。不幸的是,此查询返回了"Star Trek Into Darkness"
这部电影,它不是原始电影系列的一部分。为了解决这个问题,我们可以使用否定来排除该文档。
使用否定查询
要使用否定词,在要排除的结果集中出现的术语前放置一个负号 -
。查询操作会从搜索结果中排除包含此术语的任何文档。由于此查询包含两个不同的术语,请用空格将它们分开。
// Create a query that searches for the phrase "star trek" while omitting "into darkness" const query = { $text: { $search: "\"star trek\" -\"into darkness\"" } }; // Include only the `title` field of each matched document const projection = { _id: 0, title: 1, }; // Find documents based on the query and projection const cursor = movies.find(query).project(projection);
使用否定术语进行查询产生以下文档
{ title: 'Star Trek' } { title: 'Star Trek: Nemesis' } { title: 'Star Trek: Insurrection' } { title: 'Star Trek: Generations' } { title: 'Star Trek: First Contact' } { title: 'Star Trek: The Motion Picture' } { title: 'Star Trek VI: The Undiscovered Country' } { title: 'Star Trek V: The Final Frontier' } { title: 'Star Trek IV: The Voyage Home' } { title: 'Star Trek III: The Search for Spock' } { title: 'Star Trek II: The Wrath of Khan' }
注意
您的查询操作可能返回一个包含匹配文档的游标引用。要了解如何检查游标中存储的数据,请参阅游标基础页面。
按相关性排序
现在,结果集反映了所需的结果,您可以使用查询投影中访问的文本搜索 textScore
来按相关性对结果进行排序
// Create a query that searches for the phrase "star trek" while omitting "into darkness"r const query = { $text: { $search: "\"star trek\" -\"into darkness\"" } }; // Sort returned documents by descending text relevance score const sort = { score: { $meta: "textScore" } }; // Include only the `title` and `score` fields in each returned document const projection = { _id: 0, title: 1, score: { $meta: "textScore" }, }; // Find documents based on the query, sort, and projection const cursor = movies .find(query) .sort(sort) .project(projection);
以这种方式查询返回以下顺序的文档。一般来说,字符串匹配的术语越多,文本相关性就越高;字符串未匹配的部分越长,文本相关性就越低。
{ title: 'Star Trek', score: 1.5 } { title: 'Star Trek: Generations', score: 1.3333333333333333 } { title: 'Star Trek: Insurrection', score: 1.3333333333333333 } { title: 'Star Trek: Nemesis', score: 1.3333333333333333 } { title: 'Star Trek: The Motion Picture', score: 1.25 } { title: 'Star Trek: First Contact', score: 1.25 } { title: 'Star Trek II: The Wrath of Khan', score: 1.2 } { title: 'Star Trek III: The Search for Spock', score: 1.2 } { title: 'Star Trek IV: The Voyage Home', score: 1.2 } { title: 'Star Trek V: The Final Frontier', score: 1.2 } { title: 'Star Trek VI: The Undiscovered Country', score: 1.2 }
有关 $text 操作符及其选项的更多信息,请参阅手册条目。