Docs 菜单
Docs 主页
/
MongoDB Atlas
/ / / /

多个子句

在此页面上

  • 定义
  • 语法
  • 选项
  • 使用
  • 评分行为
  • 示例
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}

每个 mustmustNotshouldfilter 子句都包含一个子句数组。即使数组只包含一个子句,也仍然使用数组语法。请参阅本页的示例

compound 使用以下词条来构造查询:

must

要将文档包含在结果中必须匹配的子句。返回的分数是子句中所有子查询的分数总和。

映射到 AND 布尔操作符。

mustNot

要将文档包含在结果中必须不能匹配的子句。mustNot 子句对返回文档的分数没有贡献。

映射到 AND NOT 布尔操作符。

should

您希望与结果所包含文档匹配的子句。与不包含 should 子句的文档相比,包含 should 子句匹配项的文档得分更高。返回的分数是子句中所有子查询的分数总和。

如果使用多个 should 子句,则可以使用 minimumShouldMatch 选项指定必须匹配的最低数量 should 子句才能将文档包含在结果中。如果省略,则 minimumShouldMatch 选项默认为 0

请参阅示例

映射到 OR 布尔操作符。

如果在复合查询中只使用了 should 子句,compound 操作符会将 should 子句的查询数组视为逻辑 OR。Atlas Search 必须找到至少一个 should 个条件的匹配项才能返回任何结果。当您指定多个 should 子句条件并将 minimumShouldMatch 选项设为 0 时,Atlas Search 会将 minimumShouldMatch 视为已设为 1,并且必须匹配至少一个条件才能返回任何结果。

filter

要将文档包含在结果中必须全部匹配的子句。filter 子句对返回文档的分数没有贡献。

例如,您可以使用 compound 操作符filter 选项将 $match 阶段替换为 $search 阶段。以下 $match 阶段筛选字段 role 具有给定值的文档 :

$match: {
"role": { "$in": [ "CLIENT", "PROFESSIONAL" ] }
}

您可以改用 compound 操作符 filter 选项:

$search: {
"compound": {
"filter": [{
"queryString": {
"defaultPath": "role",
"query": "CLIENT OR PROFESSIONAL"
}
}]
}
}

请参阅另一过滤示例

score
修改整个 compound 子句的分数。 您可以使用score来提高、替换或以其他方式更改分数。如果不指定score ,则返回的分数是生成匹配项的mustshould子句中所有子查询的分数之和。要了解更多信息,请参阅评分行为。

您可以使用任何带有任何顶层操作符(例如自动完成文本跨度)的子句来指定查询条件。

通过文档在文档上生成匹配项的每个子句获得的分数求和,Atlas Search 对结果集中的文档进行评分。 只有mustshould子句参与评分。结果集按分数从最高到最低排序。

下表显示了影响和不影响分数的 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 操作符。

以下示例使用 mustmustNot 子句的组合来构建查询。must 子句使用文本操作符在 description 字段中搜索术语 varieties。要匹配文档,它必须满足 must 子句。mustNot 子句对 description 字段中的术语 apples 执行搜索操作。要匹配文档,它必须满足 mustNot 子句。

1db.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 指定优先搜索包含单词 Fuji 的文档。

对于此查询,$project 管道阶段排除除 _id 之外的所有文档字段,并添加了一个 score 字段,该字段显示文档的相关性分数。

1db.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 中的示例。

以下查询还为结果中的所有文档指定 3constant分数。对于此查询,$project 管道阶段排除了除 _id 之外的所有文档字段,并添加了 score 字段。

1db.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 中的示例。

在包含多个 should 子句的查询中,可以使用 miniumumShouldMatch 选项来指定必须匹配才能返回结果的最小子句数。

下面的查询有一个 must 子句和两个 should 子句,minimumShouldMatch 值为 1。文档必须在 description 字段中包含术语 varieties,必须在描述字段中包含 FujiGolden Delicious,才能被包含在结果集中。

1db.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 其行为与must相同,但返回文档的分数中不考虑filter子句,因此不会影响返回文档的顺序。

以下查询使用了以下子句:

  • mustfilter 指定必须满足的搜索条件。

  • should 指定包含单词 banana 的文档的首选项。should 子句不包含 minimumShouldMatch 选项。如果省略 minimumShouldMatch,则默认为 0

1db.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 管道阶段,用于执行以下操作:

  • 排除除 _iddescription 之外的所有字段。

  • 添加 score 字段,显示文档的相关性分数。

1db.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 子句中指定的词语 applesbananas

  • 包含 _id: 1 的文档比包含 _id: 2 的文档得分更高,因为它包含查询 的should 子句中指定的术语 varieties

➤ 尝试 Atlas Search Playground 中的示例。

以下示例使用嵌套的 compound 子句构造查询。对于此示例,fruit 集合具有针对 typecategoryin_stock 字段的索引,且其文本字段使用默认分析器。此查询要求文档仅满足以下 should 子句之一:

  • type 字段中包含单词 apple

  • category 字段中包含 organic 一词,并在 in_stock 字段中使用值 true

1db.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 中的示例。

后退

自动补全