定义
语法
compound 通过以下语法实现:
1 { 2 $search: { 3 "index": <index name>, // optional, defaults to "default" 4 "compound": { 5 <must | mustNot | should | filter>: [ { <clauses> } ], 6 "score": <options> 7 } 8 } 9 }
每个 must、mustNot、should 和 filter 子句都包含一个子句数组。即使数组只包含一个子句,也仍然使用数组语法。请参阅本页的示例。
选项
compound 使用以下词条来构造查询:
要将文档包含在结果中必须匹配的子句。返回的分数是子句中所有子查询的分数总和。 映射到 | ||||||||||||||
要将文档包含在结果中必须不能匹配的子句。 映射到 | ||||||||||||||
您希望与结果所包含文档匹配的子句。与不包含 如果使用多个 请参阅示例。 映射到 如果在复合查询中仅使用 | ||||||||||||||
要将文档包含在结果中必须全部匹配的子句。 例如,您可以使用 您可以改用 | ||||||||||||||
| 修改整个 |
使用
您可以使用任何带有任何顶层操作符(例如自动完成、文本或跨度)的子句来指定查询条件。
为优化性能,请将非评分操作符(例如 equals、range 和 in)放入 filter 子句中,避免不必要的评分操作。如果您想运行必须作为 OR 条件求值的操作,请在顶层 filter 中嵌套一个 should子句。
例子
[ { $search: { index: "default", compound: { filter: [ { compound: { should: [ { equals: { path: "accommodates", value: 2 } }, { range: { path: "pricePerNight", lte: 200 } } ] } } ] } } } ]
评分行为
MongoDB搜索通过文档在文档上生成匹配项的每个子句获得的分数求和,对结果设立进行评分。只有 must 和 should 子句参与评分。结果设立按分数从最高到最低排序。
下表显示了影响和不影响分数的 compound子句。
子句 | 影响分数 |
|---|---|
| |
| |
| |
|
您可以用 score 选项提高或替换整个复合查询的分数。有关替换整个复合分数的示例,请参阅下面的 复合分数示例 。您还可以用分数来提高或更改每个子句中每个子查询的分数。有关 compound 操作符子句中已更改分数的部分示例,请参阅修改分数。
示例
您可以在MongoDB Search Playground 或集群中尝试以下示例。
样本集合
本页上的示例使用名为 fruit 的集合,其中包含以下文档:
1 { 2 "_id" : 1, 3 "type" : "apple", 4 "description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.", 5 "category" : "nonorganic", 6 "in_stock" : false 7 }, 8 { 9 "_id" : 2, 10 "type" : "banana", 11 "description" : "Bananas are usually sold in bunches of five or six.", 12 "category" : "nonorganic", 13 "in_stock" : true 14 }, 15 { 16 "_id" : 3, 17 "type" : "pear", 18 "description" : "Bosc and Bartlett are the most common varieties of pears.", 19 "category" : "organic", 20 "in_stock" : true 21 }
样本索引
fruit 集合有一个带有动态映射的默认索引,可自动为集合中的所有字段建立索引,并使用默认的标准分析器。standard 分析器将所有单词转为小写并忽略常见的停用词("the", "a", "and", 等)。
样本查询
以下查询演示了MongoDB搜索查询中的$search compound操作符。
must 和 mustNot 示例
以下示例使用 must 和 mustNot 子句的组合来构建查询。must 子句使用文本操作符在 description 字段中搜索术语 varieties。要匹配文档,它必须满足 must 子句。mustNot 子句对 description 字段中的术语 apples 执行搜索操作。要匹配文档,它必须不满足 mustNot 子句。
1 db.fruit.aggregate([ 2 { 3 "$search": { 4 "compound": { 5 "must": [{ 6 "text": { 7 "query": "varieties", 8 "path": "description" 9 } 10 }], 11 "mustNot": [{ 12 "text": { 13 "query": "apples", 14 "path": "description" 15 } 16 }] 17 } 18 } 19 } 20 ])
上述查询返回的文档包含 _id: 3,因为其 description 字段包含单词 varieties,而不包含 apples。
➤ 在MongoDB Search Playground中尝试一下。
must 和 should 示例
以下查询使用 must 指定必须满足的搜索条件,使用 should 指定优先搜索包含单词 Fuji 的文档。
对于此查询,$project 管道阶段排除除 _id 之外的所有文档字段,并添加了一个 score 字段,该字段显示文档的相关性分数。
1 db.fruit.aggregate([ 2 { 3 "$search": { 4 "compound": { 5 "must": [{ 6 "text": { 7 "query": "varieties", 8 "path": "description" 9 } 10 }], 11 "should": [{ 12 "text": { 13 "query": "Fuji", 14 "path": "description" 15 } 16 }] 17 } 18 } 19 }, 20 { 21 "$project": { 22 "score": { "$meta": "searchScore" } 23 } 24 } 25 ])
{ "_id" : 1, "score" : 0.6425117254257202 } { "_id" : 3, "score" : 0.21649497747421265 }
包含 _id: 1 的文档分数较高,因为其 description 字段包含单词 Fuji,并且满足 should 子句。
➤ 在MongoDB Search Playground中尝试一下。
以下查询还为结果中的所有文档指定 3 的 constant分数。对于此查询,$project 管道阶段排除了除 _id 之外的所有文档字段,并添加了 score 字段。
1 db.fruit.aggregate([ 2 { 3 "$search": { 4 "compound": { 5 "must": [{ 6 "text": { 7 "query": "varieties", 8 "path": "description" 9 } 10 }], 11 "should": [{ 12 "text": { 13 "query": "Fuji", 14 "path": "description" 15 } 16 }], 17 "score": { "constant": { "value": 3 } } 18 } 19 } 20 }, 21 { 22 "$project": { 23 "score": { "$meta": "searchScore" } 24 } 25 } 26 ])
[ { _id: 1, score: 3 }, { _id: 3, score: 3 } ]
这两个文档获得相同的分数,因为查询中的 constant 选项将结果中每个文档的分数替换为数字 3。
➤ 在MongoDB Search Playground中尝试一下。
minimumShouldMatch 示例
在包含多个 should 子句的查询中,可以使用 miniumumShouldMatch 选项来指定必须匹配才能返回结果的最小子句数。
下面的查询有一个 must 子句和两个 should 子句,minimumShouldMatch 值为 1。文档必须在 description 字段中包含术语 varieties,必须在描述字段中包含 Fuji 或 Golden Delicious,才能被包含在结果集中。
1 db.fruit.aggregate([ 2 { 3 $search: { 4 "compound": { 5 "must": [{ 6 "text": { 7 "query": "varieties", 8 "path": "description" 9 } 10 }], 11 "should": [{ 12 "text": { 13 "query": "Fuji", 14 "path": "description" 15 } 16 }, 17 { 18 "text": { 19 "query": "Golden Delicious", 20 "path": "description" 21 } 22 }], 23 "minimumShouldMatch": 1 24 } 25 } 26 } 27 ])
1 { 2 "_id" : 1, 3 "type" : "apple", 4 "description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.", 5 "category" : "nonorganic", 6 "in_stock" : false 7 }
带有 _id: 1 的文档匹配 must 子句和两个 should 子句中的第一个。
➤ 在MongoDB Search Playground中尝试一下。
filter 示例
filter 其行为与must相同,但返回文档的分数中不考虑filter子句,因此不会影响返回文档的顺序。
以下查询使用了以下子句:
must和filter指定必须满足的搜索条件。should指定包含单词banana的文档的首选项。should子句不包含minimumShouldMatch选项。如果省略minimumShouldMatch,则默认为0。
1 db.fruit.aggregate([ 2 { 3 "$search": { 4 "compound": { 5 "must": [{ 6 "text": { 7 "query": "varieties", 8 "path": "description" 9 } 10 }], 11 "should": [{ 12 "text": { 13 "query": "banana", 14 "path": "description" 15 } 16 }], 17 "filter": [{ 18 "text": { 19 "query": "granny", 20 "path": "description" 21 } 22 }] 23 } 24 } 25 } 26 ])
1 { 2 "_id" : 1, 3 "type" : "apple", 4 "description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.", 5 "category" : "nonorganic", 6 "in_stock" : false 7 }
上述文档满足所有包含要求:
must子句和filter子句都匹配。未指定
minimumShouldMatch值,因此默认为0。因此,should子句失败,但仍返回文档。
➤ 在MongoDB Search Playground中尝试一下。
在带有 filter 子句的集群数据查询中,您可以将 $match 替换为 $in。以下查询演示了如何在 $search 阶段使用 filter 来指定必须匹配的搜索词。该查询还使用 should 来指定对包含术语varieties 的文档的偏好。该查询包括用于执行以下操作的 $project管道阶段:
排除除
_id和description之外的所有字段。添加
score字段,显示文档的相关性分数。
1 db.fruit.aggregate([ 2 { 3 "$search": { 4 "compound": { 5 "filter": [{ 6 "text": { 7 "query": ["apples", "bananas"], 8 "path": "description" 9 } 10 }], 11 "should": [{ 12 "text": { 13 "query": "varieties", 14 "path": "description" 15 } 16 }] 17 } 18 } 19 }, 20 { 21 "$project": { 22 "description": 1, 23 "score": { "$meta": "searchScore" } 24 } 25 } 26 ])
1 [ 2 { 3 _id: 1, 4 description: 'Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp. The most popular varieties are McIntosh, Gala, and Granny Smith.', 5 score: 0.36074575781822205 6 }, 7 { 8 _id: 2, 9 description: 'Bananas are usually sold in bunches of five or six.', 10 score: 0 11 } 12 ]
结果中的文档满足所有包含要求:
两个文档都包含在查询的
filter子句中指定的词语apples或bananas。包含
_id: 1的文档比包含_id: 2的文档得分更高,因为它包含查询 的should子句中指定的术语varieties。
➤ 在MongoDB Search Playground中尝试一下。
嵌套示例
以下示例使用嵌套的 compound 子句构造查询。对于此示例,fruit 集合具有针对 type、category 和 in_stock 字段的索引,且其文本字段使用默认分析器。此查询要求文档仅满足以下 should 子句之一:
在
type字段中包含单词apple。在
category字段中包含organic一词,并在in_stock字段中使用值true。
1 db.fruit.aggregate([ 2 { 3 $search: { 4 "compound": { 5 "should": [ 6 { 7 "text": { 8 "query": "apple", 9 "path": "type" 10 } 11 }, 12 { 13 "compound": { 14 "must": [ 15 { 16 "text": { 17 "query": "organic", 18 "path": "category" 19 } 20 }, 21 { 22 "equals": { 23 "value": true, 24 "path": "in_stock" 25 } 26 } 27 ] 28 } 29 } 30 ], 31 "minimumShouldMatch": 1 32 } 33 } 34 } 35 ])
1 { 2 "_id" : 3, 3 "type" : "pear", 4 "description" : "Bosc and Bartlett are the most common varieties of pears.", 5 "category" : "organic", 6 "in_stock" : true 7 } 8 { 9 "_id" : 1, 10 "type" : "apple", 11 "description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.", 12 "category" : "nonorganic", 13 "in_stock" : false 14 }
结果中的文档满足所有包含要求:
_id: 3的文档与嵌套在第二个should子句中的must子句匹配。_id: 1的文档与第一个should子句匹配。
➤ 在MongoDB Search Playground中尝试一下。
元数据示例
以下查询使用 $searchMeta 管道阶段或 $search 阶段的 $$SEARCHMETA 变量检索元数据,以返回 fruit 集合中的类别数。