Docs 主页 → 开发应用程序 → MongoDB Manual
$text
注意
本页介绍自管理(非 Atlas)部署的文本搜索功能。对于 MongoDB Atlas 上托管的数据,MongoDB 提供了改进的全文搜索解决方案,即 Atlas Search。
本页介绍用于自托管部署的 $text
操作符。
定义
$text
$text
对使用文本索引建立索引的字段内容执行文本搜索。
兼容性
可以使用 $text
查找托管在以下环境中的部署:
MongoDB Atlas :用于在云中部署 MongoDB 的完全托管服务
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
语法
$text
表达式采用以下语法:
{ $text: { $search: <string>, $language: <string>, $caseSensitive: <boolean>, $diacriticSensitive: <boolean> } }
$text
操作符接受包含以下字段的文本查询文档:
字段 | 类型 | 说明 |
---|---|---|
$search | 字符串 | |
$language | 字符串 | 可选。用于确定搜索停用词列表以及词干分析器和分词器规则的语言。如果未指定,搜索将使用索引的默认语言。有关支持的语言,请参阅文本搜索语言。 如果您指定的语言值为 |
$caseSensitive | 布尔 | |
$diacriticSensitive | 布尔 |
默认情况下, $text
操作符不返回按结果分数排序的结果。有关按文本搜索分数排序的更多信息,请参阅文本分数文档。
行为
限制
查询最多可以指定一个
$text
表达式。$text
查询不能出现在$nor
表达式中。$text
查询不能出现在$elemMatch
查询表达式或$elemMatch
投影表达式中。如果查询包含
$text
表达式,则不能使用hint()
指定用于查询的索引。如果查询包含
$text
表达式,则无法指定$natural
排序顺序。不能将需要特殊文本索引的
$text
表达式与需要其他类型特殊索引的查询操作符组合使用。例如,您不能将$text
表达式与$near
操作符组合使用。视图不支持文本搜索。
$text
不支持使用Stable API V 1创建索引。
如果在聚合中使用$text
操作符,则以下限制也适用。
$search
字段
在$search
字段中,指定$text
操作符解析并用于查询文本索引的string。
$text
操作符将string中的大多数标点符号视为分隔符,但否定术语的连字符减号 ( -
) 或指定短语的转义双引号\"
除外。
注意
$search
$text
表达式的 字段与 Atlas Search 提供的 $search 聚合阶段 不同。$search
聚合阶段对指定字段执行全文搜索,并且仅在 MongoDB Atlas 上可用。
短语
要匹配短语(而不是单个词),请将短语包含在转义双引号 (\"
) 中,如下所示:
"\"ssl certificate\""
如果$search
$text
操作的string包含短语和单个术语,则搜索仅匹配包含该短语的文档。
例如,传递了一个 $search
字符串:
"\"ssl certificate\" authority key"
$text
操作符搜索短语"ssl
certificate"
。
注意
不能使用 $text
操作符来搜索多个短语。
否定
在单词前面加上连字符减号 (-
) 可以否定单词:
否定词从结果集中排除包含否定词的文档。
当传递仅包含否定词的搜索字符串时,文本搜索将不会匹配任何文档。
带连字符的单词,例如
pre-market
,不是否定词。如果在带连字符的单词中使用,$text
操作符会将减号连字符 (-
) 视为分隔符。要在本实例中否定单词market
,请在pre
和 之间添加一个空格,即-market
pre -market
。
$text
操作符使用逻辑AND
操作符将所有否定词添加到查询中。
匹操作
非索引字
$text
操作符忽略特定语言的停用词,例如英语中的the
和and
。
词干处理
对于不区分大小写和不区分变音符号的搜索,$text
操作符匹配完整的 词干 单词。因此,如果文档字段包含单词blueberry
,则对术语blue
的搜索将不匹配。但是,blueberry
或blueberries
会匹配。
区分大小写的搜索和词干
对于区分大小写的搜索(即$caseSensitive: true
),如果后缀词干包含大写字母,则$text
操作符将匹配精确的单词。
区分音调符号的搜索和词干
对于区分变音符号的搜索(即$diacriticSensitive: true
),如果后缀词干包含一个或多个变音符号,则$text
操作符将匹配精确的单词。
不区分大小写。
$text
操作符默认为文本索引不区分大小写:
版本 3 的文本索引对带或不带变音符号的拉丁字符以及来自非拉丁字母的字符(例如西里尔字母)不区分大小写。请参阅文本索引,了解详细信息。
早期版本的
text
索引对于不带变音符号的拉丁字符不区分大小写;即,对于[A-z]
。
$caseSensitive
选项
要支持区分大小写的搜索(其中 text
索引不区分大小写),请指定 $caseSensitive: true
。
区分大小写的搜索进程
在执行区分大小写的搜索 ( $caseSensitive: true
) 时,如果text
索引不区分大小写,则$text
操作符:
首先,搜索
text
索引是否存在不区分大小写和变音符号的匹配项。然后,为了仅返回与搜索术语大小写匹配的文档,
$text
查询操作包括一个额外的阶段,用于过滤掉与指定大小写不匹配的文档。
对于区分大小写的搜索(即$caseSensitive: true
),如果后缀词干包含大写字母,则$text
操作符将匹配精确的单词。
指定 $caseSensitive: true
可能会影响性能。
提示
另请参阅:
不区分变音符号
$text
操作符默认为文本索引不区分变音符号:
版本 3 文本索引不区分变音符号。也就是说,索引不区分包含变音标记的字符及其未标记的对应字符,例如
é
、ê
和e
。早期版本的
text
索引会区分变音符号。
$diacriticSensitive
选项
要支持针对 text
索引进行区分变音符号的文本搜索,请指定 $diacriticSensitive: true
。
针对早期版本的text
索引的文本搜索本质上是区分变音符号的,并且不能不区分变音符号。因此, $text
操作符的$diacriticSensitive
选项对早期版本的text
索引没有影响。
区分音调符号的搜索过程
要对版本3 text
索引执行区分变音符号的文本搜索 ( $diacriticSensitive:
true
), $text
操作符:
首先搜索
text
索引,该索引不区分变音符号。然后,为了仅返回与术语的变音符号匹配的文档,
$text
查询操作包括一个额外的阶段,用于滤除不匹配的文档。
指定 $diacriticSensitive: true
可能会影响性能。
要对早期版本的text
索引执行区分变音符号的搜索, $text
操作符会搜索区分变音符号的text
索引。
对于区分变音符号的搜索,如果后缀词干包含一个或多个变音符号,则$text
操作符将匹配精确的单词。
提示
另请参阅:
文本分数
$text
操作符会为索引字段中包含搜索术语的每个文档分配一个分数。该分数表示文档与给定文本搜索查询的相关性。分数可以是sort()
方法规范的一部分,也可以是投影表达式的一部分。 { $meta: "textScore" }
表达式提供有关$text
操作处理的信息。有关访问投影或排序的分数的详细信息,请参阅$meta
投影操作符。
举例
以下示例假设集合 articles
在字段 subject
上具有版本 3 文本索引:
db.articles.createIndex( { subject: "text" } )
用以下文档填充集合:
db.articles.insertMany( [ { _id: 1, subject: "coffee", author: "xyz", views: 50 }, { _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 }, { _id: 3, subject: "Baking a cake", author: "abc", views: 90 }, { _id: 4, subject: "baking", author: "xyz", views: 100 }, { _id: 5, subject: "Café Con Leche", author: "abc", views: 200 }, { _id: 6, subject: "Сырники", author: "jkl", views: 80 }, { _id: 7, subject: "coffee and cream", author: "efg", views: 10 }, { _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 } ] )
搜索单个单词
以下查询指定 coffee
的 $search
字符串:
db.articles.find( { $text: { $search: "coffee" } } )
此查询返回在带索引的 subject
字段中包含 coffee
这个词(或更准确地说,该单词的词干版本)的文档:
{ _id: 1, subject: 'coffee', author: 'xyz', views: 50 }, { _id: 7, subject: 'coffee and cream', author: 'efg', views: 10 }, { _id: 2, subject: 'Coffee Shopping', author: 'efg', views: 5 }
匹配任何搜索词
如果搜索string是以空格分隔的string,则$text
操作符会对每个术语执行逻辑OR
搜索,并返回包含任何术语的文档。
以下查询指定由空格分隔的三个术语组成的 $search
字符串 "bake coffee cake"
:
db.articles.find( { $text: { $search: "bake coffee cake" } } )
此查询返回带索引的 subject
字段中包含 bake
、coffee
或 cake
的文档,或更准确地说,包含这些单词的词干提取版本:
{ "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg", "views" : 5 } { "_id" : 7, "subject" : "coffee and cream", "author" : "efg", "views" : 10 } { "_id" : 1, "subject" : "coffee", "author" : "xyz", "views" : 50 } { "_id" : 3, "subject" : "Baking a cake", "author" : "abc", "views" : 90 } { "_id" : 4, "subject" : "baking", "author" : "xyz", "views" : 100 }
搜索短语
要将确切的短语作为单个术语进行匹配,需要对引号进行转义。
以下查询搜索短语 coffee shop
:
db.articles.find( { $text: { $search: "\"coffee shop\"" } } )
此查询会返回包含短语 coffee shop
的文档:
{ "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg", "views" : 5 }
提示
另请参阅:
排除包含术语的文档
否定术语是以减号-
为前缀的术语。如果否定一个术语, $text
操作符将从结果中排除包含这些术语的文档。
以下示例搜索包含单词 coffee
但不包含术语 shop
的文档,或者更准确地说,包含这些单词的词干提取版本:
db.articles.find( { $text: { $search: "coffee -shop" } } )
该查询返回以下文档:
{ "_id" : 7, "subject" : "coffee and cream", "author" : "efg", "views" : 10 } { "_id" : 1, "subject" : "coffee", "author" : "xyz", "views" : 50 }
搜索其他语言
使用$text
表达式中可选的$language
字段指定用于确定停用词列表的语言以及string的词干分析器和分词器规则。
如果您指定的语言值为"none"
,则文本搜索将使用简单的分词,没有停用词列表,也没有词干提取。
以下查询指定 es
,即西班牙语,来作为决定分词、词干提取和停用词的语言:
db.articles.find( { $text: { $search: "leche", $language: "es" } } )
该查询返回以下文档:
{ "_id" : 5, "subject" : "Café Con Leche", "author" : "abc", "views" : 200 } { "_id" : 8, "subject" : "Cafe con Leche", "author" : "xyz", "views" : 10 }
$text
表达式还可以按名称spanish
接受语言。有关支持的语言,请参阅文本搜索语言。
提示
另请参阅:
不区分大小写和不区分变音符号搜索
$text
操作符遵循text
索引的大小写和变音符号不敏感机制。 3 text
版本索引不区分变音符号,并将其不区分大小写的功能扩展为包含西里尔字母和带变音符号的字符。有关详细信息,请参阅文本索引不区分大小写和文本索引不区分变音符号。
以下查询对术语 сы́рники
或 CAFÉS
执行不区分大小写和变音符号的文本搜索:
db.articles.find( { $text: { $search: "сы́рники CAFÉS" } } )
使用版本 3 text
索引,查询将匹配以下文档。
{ "_id" : 6, "subject" : "Сырники", "author" : "jkl", "views" : 80 } { "_id" : 5, "subject" : "Café Con Leche", "author" : "abc", "views" : 200 } { "_id" : 8, "subject" : "Cafe con Leche", "author" : "xyz", "views" : 10 }
如果使用以前版本的text
索引,该查询不会匹配任何文档。
执行区分大小写的搜索
要启用区分大小写搜索,请指定 $caseSensitive: true
。指定 $caseSensitive: true
可能会影响性能。
区分大小写的字词搜索
以下查询对术语 Coffee
执行区分大小写的搜索:
db.articles.find( { $text: { $search: "Coffee", $caseSensitive: true } } )
搜索仅匹配符合以下条件的文档:
{ "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg", "views" : 5 }
提示
另请参阅:
区分大小写的短语搜索
以下查询对短语 Café Con Leche
执行区分大小写的搜索:
db.articles.find( { $text: { $search: "\"Café Con Leche\"", $caseSensitive: true } } )
搜索仅匹配符合以下条件的文档:
{ "_id" : 5, "subject" : "Café Con Leche", "author" : "abc", "views" : 200 }
提示
另请参阅:
区分大小写,需含否定词
否定术语是以减号-
为前缀的术语。如果否定一个术语, $text
操作符将从结果中排除包含这些术语的文档。您还可以指定否定术语区分大小写。
以下示例对包含单词 Coffee
但 不包含小写单词 shop
的文档(或更准确地说,单词的词干版本)执行区分大小写的搜索:
db.articles.find( { $text: { $search: "Coffee -shop", $caseSensitive: true } } )
查询匹配以下文档:
{ "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg" }
提示
另请参阅:
区分变音符号的搜索
如要对版本 3 的文本索引启用变音符号敏感搜索,请指定 $diacriticSensitive: true
。指定 $diacriticSensitive: true
可能会影响性能。
针对术语进行的区分变音符号的搜索
以下查询将对 CAFÉ
一词或(更准确地说是)该词的词干版本执行区分变音符号的文本搜索:
db.articles.find( { $text: { $search: "CAFÉ", $diacriticSensitive: true } } )
查询只匹配以下文档:
{ "_id" : 5, "subject" : "Café Con Leche", "author" : "abc" }
提示
区分变音符号并使用否定词
$diacriticSensitive
选项也适用于否定术语。否定术语是以减号-
为前缀的术语。如果否定一个术语, $text
操作符将从结果中排除包含这些术语的文档。
以下查询对包含术语 leches
但不包含术语 cafés
,或更准确地说是这些单词的词干提取版本的文档执行区分变音符号的文本搜索:
db.articles.find( { $text: { $search: "leches -cafés", $diacriticSensitive: true } } )
查询匹配以下文档:
{ "_id" : 8, "subject" : "Cafe con Leche", "author" : "xyz" }
提示
文本搜索分数示例
返回文本搜索分数
以下查询对术语 cake
进行文本搜索,并在投影文档中使用 $meta
操作符将相关性分数追加到每个匹配的文档:
db.articles.find( { $text: { $search: "cake" } }, { score: { $meta: "textScore" } } )
返回的文档包含一个附加 字段 score
,其中包含文档的相关性分数:
{ "_id" : 3, "subject" : "Baking a cake", "author" : "abc", "views" : 90, "score" : 0.75 }
提示
另请参阅:
按文本搜索分数排序
您可以在
{ $meta: "textScore" }
中指定sort()
表达式,而无需同时指定投影中的表达式。例如:db.articles.find( { $text: { $search: "cake" } } ).sort( { score: { $meta: "textScore" } } ) 因此,可以根据搜索相关性对结果文档进行排序,而无需对
textScore
投影。如果您在
{ $meta: "textScore" }
投影 和 中都包含sort()
表达式,则投影和排序文档可以具有不同的表达式字段名称。db.articles.find( { $text: { $search: "cake" } } , { score: { $meta: "textScore" } } ).sort( { ignoredName: { $meta: "textScore" } } )
在 MongoDB 4.2 中,要按文本分数排序,请同时在投影文档和排序表达式中包含相同的
$meta
表达式。以下查询搜索术语coffee
并按分数降序对结果进行排序:db.articles.find( { $text: { $search: "coffee" } }, { score: { $meta: "textScore" } } ).sort( { score: { $meta: "textScore" } } ) 此查询会返回按分数降序排序的匹配文档。
提示
另请参阅:
返回前 2 个匹配文档
将 limit()
方法与 sort()
结合使用可返回前 n
个匹配的文档。
以下查询搜索术语 coffee
并按降序分数对结果进行排序,将结果限制为前两个匹配的文档:
db.articles.find( { $text: { $search: "coffee" } }, { score: { $meta: "textScore" } } ).sort( { score: { $meta: "textScore" } } ).limit(2)
提示
另请参阅:
使用其他查询和排序表达式的文本搜索
以下查询搜索 author
等于 "xyz"
且带索引的字段 subject
包含术语 coffee
或 bake
的文档。该操作还指定按 date
升序排列,然后按文本搜索分数降序排列:
db.articles.find( { author: "xyz", $text: { $search: "coffee bake" } }, { score: { $meta: "textScore" } } ).sort( { date: 1, score: { $meta: "textScore" } } )