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 的值必须小于或等于查询中 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 中的示例。

后退

自动补全