定义
语法
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 }
Each must, mustNot, should, and filter clause contains an array of subclauses. Use array syntax even if the array contains only one subclause. See the examples on this page.
选项
compound 使用以下词条来构造查询:
要将文档包含在结果中必须匹配的子句。返回的分数是子句中所有子查询的分数总和。 映射到 | ||||||||||||||
要将文档包含在结果中必须不能匹配的子句。 映射到 | ||||||||||||||
您希望与结果所包含文档匹配的子句。与不包含 如果使用多个 映射到 如果在复合查询中仅使用 | ||||||||||||||
要将文档包含在结果中必须全部匹配的子句。 例如,您可以使用 您可以改用 | ||||||||||||||
| 修改整个 | |||||||||||||
| 要从基于此查询的计数重新计算中排除的分面(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 或集群中尝试以下示例。
样本集合
本页上的示例使用名为 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 and mustNot Example
以下示例使用 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 and should Example
以下查询使用 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 集合中的类别数。