Docs 菜单

Docs 主页开发应用程序MongoDB 驱动程序Node.js 驱动程序

搜索文本

在此页面上

  • 概述
  • 举例
  • 单词查询
  • 按短语查询
  • 带否定词的查询
  • 按相关性排序

文本搜索允许您在集合中搜索字符串类型字段以查找指定的单词或短语。您可以使用 $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" });

提示

在文本索引中指定字段权重

创建复合文本索引时,您可以指定权重选项,以对索引中某些文本字段进行优先排序。执行文本搜索时,字段权重会影响 MongoDB 计算每个匹配文档的文本搜索分数的方式。

要详细了解创建文本索引时指定字段权重,请参阅索引指南中的文本索引部分。

每个集合只能创建一个文本索引。每个文本搜索都会查询该索引中指定的所有字段以查找匹配项。

要了解有关文本索引的更多信息,请参阅服务器手册中的文本索引

此示例通过搜索包含 "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);

使用短语"star trek"而不仅仅是词语"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 (通过查询投影中的$meta操作符访问)按相关性对结果进行排序:

// 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 操作符及其选项的更多信息,请参阅手册条目。

← 按地理空间搜索