多个子句
定义
compound
compound
操作符将两个或多个操作符合并到一个查询中。compound
查询的每个元素称为子句,每个子句由一个或多个子查询组成。Atlas Search 提供一个包含指导的示例复合查询模板。要了解更多信息,请参阅 查看查询指导模板。
语法
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
使用以下词条来构造查询:
要将文档包含在结果中必须匹配的子句。返回的分数是子句中所有子查询的分数总和。 映射到 | ||||||||||||||
要将文档包含在结果中必须不能匹配的子句。 映射到 | ||||||||||||||
您希望与结果所包含文档匹配的子句。与不包含 如果使用多个 请参阅示例。 映射到 如果在复合查询中只使用了 | ||||||||||||||
要将文档包含在结果中必须全部匹配的子句。 例如,您可以使用
您可以改用
请参阅另一过滤示例。 | ||||||||||||||
score |
使用
评分行为
通过文档在文档上生成匹配项的每个子句获得的分数求和,Atlas Search 对结果集中的文档进行评分。 只有must
和should
子句参与评分。结果集按分数从最高到最低排序。
下表显示了影响和不影响分数的 compound
子句。
子句 | 影响分数 | 对分数没有贡献 |
---|---|---|
filter | ||
must | ||
mustNot | ||
should |
您可以用 score
选项提高或替换整个复合查询的分数。有关替换整个复合分数的示例,请参阅下面的 复合分数示例 。您还可以用分数来提高或更改每个子句中每个子查询的分数。有关 compound
操作符子句中已更改分数的部分示例,请参阅修改分数。
示例
您可以在 Atlas Search Playground 或 Atlas 集群中尝试以下示例。
样本集合
本页上的示例使用名为 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",
等)。
样本查询
以下查询演示了 Atlas Search 查询中的 $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
。
➤ 尝试 Atlas 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
子句。
➤ 尝试 Atlas 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
。
➤ 尝试 Atlas 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
子句中的第一个。
➤ 尝试 Atlas 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
子句失败,但仍返回文档。
➤ 尝试 Atlas Search Playground 中的示例。
在使用 filter
子句对 Atlas 集群上的数据进行查询时,可将 $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
。
➤ 尝试 Atlas 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
子句匹配。
➤ 尝试 Atlas Search Playground 中的示例。