定义
语法
compound 通过以下语法实现:
1 { 2 $search: { 3 "index": <index name>, // optional, defaults to "default" 4 "compound": { 5 <must | mustNot | should | filter>: [ { <clauses> } ], 6 "score": <options>, 7 "doesNotAffect": "<facet-to-exclude>" | [<array-of-facets>] 8 } 9 } 10 }
每个 must、mustNot、should 和 filter 子句都包含一个子句数组。即使数组只包含一个子句,也仍然使用数组语法。请参阅本页的示例。
选项
compound 使用以下词条来构造查询:
要将文档包含在结果中必须匹配的子句。返回的分数是子句中所有子查询的分数总和。 映射到 | ||||||||||||||
要将文档包含在结果中必须不能匹配的子句。 映射到 | ||||||||||||||
您希望与结果所包含文档匹配的子句。与不包含 如果使用多个 请参阅示例。 映射到 如果在复合查询中仅使用 | ||||||||||||||
要将文档包含在结果中必须全部匹配的子句。 For example, you can replace the 您可以改用 请参阅另一过滤示例。 | ||||||||||||||
| ||||||||||||||
| 要从基于此查询的计数重新计算中排除的分面(Facet)或分面(Facet)列表。值必须是 |
使用
您可以使用任何带有任何顶层操作符(例如自动完成、文本或跨度)的子句来指定查询条件。
To optimize performance, place non-scoring operators such as equals, range, and in in the filter clause to avoid unnecessary scoring operations. If you want to run multiple operations that must be evaluated as an OR condition, nest a should clause within the top-level filter.
例子
[ { $search: { index: "default", compound: { filter: [ { compound: { should: [ { equals: { path: "accommodates", value: 2 } }, { range: { path: "pricePerNight", lte: 200 } } ] } } ] } } } ]
评分行为
MongoDB搜索通过文档在文档上生成匹配项的每个子句获得的分数求和,对结果设立进行评分。只有 must 和 should 子句参与评分。结果设立按分数从最高到最低排序。
下表显示了影响和不影响分数的 compound子句。
子句 | 影响分数 |
|---|---|
| |
| |
| |
|
You can boost or replace the score of the entire compound query using the score option. For an example of replacing the entire compound score, see Compound Score Example below. You can use score to also boost or alter the score for each subquery in each clause. For some examples of altered scores in compound operator clauses, see Modify the Score.
示例
您可以在MongoDB Search Playground 或集群中尝试以下示例。
样本集合
To run the sample queries on this page, create a collection named fruit on your cluster and insert the following documents into the collection:
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 }
样本索引
To run the sample queries on this page, create the following MongoDB Search index named default on the fruit sample collection. The index definition configures MongoDB Search to do the following:
fruit使用默认 标准 分析器提取令牌,动态索引 集合中的所有字段。standard分析器将所有单词转为小写,并忽略常见的停用词,例如"the"、"a"、"and"等。
1 { 2 "mappings": { 3 "dynamic": true, 4 "fields": { 5 "type": [ 6 { "type": "string" }, 7 { "type": "token" } 8 ] 9 } 10 } 11 }
样本查询
以下查询演示了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中尝试一下。
When a $match stage follows a $search stage, you can improve query performance by moving the match conditions into a filter clause within the $search stage. MongoDB Search applies filter conditions during the search instead of re-scanning the result set to run the $match stage.
Consider the following pipeline, which searches the description field for the term varieties and then uses $match with $in to keep only apples and bananas:
1 db.fruit.aggregate([ 2 { 3 "$search": { 4 "text": { 5 "query": "varieties", 6 "path": "description" 7 } 8 } 9 }, 10 { 11 "$match": { 12 "type": { "$in": [ "apple", "banana" ] } 13 } 14 }, 15 { 16 "$project": { 17 "description": 1, 18 "score": { "$meta": "searchScore" } 19 } 20 } 21 ])
1 [ 2 { 3 _id: 1, 4 description: 'Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.', 5 score: 0.20814445614814758 6 } 7 ]
The following query replaces the $match stage with a filter clause that uses the equals operator on the type field. The $search stage uses the compound operator to combine the following clauses:
must子句在description字段中匹配varieties搜索术语filter子句匹配apple和banana类型
The $project stage does the following:
排除
_id和description之外的所有字段添加一个
score字段,其中包含文档的相关性分数
1 db.fruit.aggregate([ 2 { 3 "$search": { 4 "compound": { 5 "must": [{ 6 "text": { 7 "query": "varieties", 8 "path": "description" 9 } 10 }], 11 "filter": [{ 12 "in": { 13 "path": "type", 14 "value": [ "apple", "banana" ] 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.', 5 score: 0.20814445614814758 6 } 7 ]
结果中的文档满足所有包含要求:
两个文档的
type值均为apple或banana,这在查询的filter子句中指定。包含
_id: 1的文档比包含_id: 2的文档得分更高,因为它包含查询 的should子句中指定的术语varieties。
嵌套示例
以下示例使用嵌套的 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 集合中的类别数。