For AI agents: a documentation index is available at https://www.mongodb.com/zh-cn/docs/llms.txt — markdown versions of all pages are available by appending .md to any URL path.
Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
MongoDB Branding Shape
Click here >
Docs 菜单

compound Operator

compound

compound操作符将两个或多个操作符组合到一个查询中。compound查询的每个元素称为子句,每个子句由一个或多个子查询组成。MongoDB 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 "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 使用以下词条来构造查询:

must

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

映射到 AND 布尔操作符。

mustNot

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

映射到 AND NOT 布尔操作符。

should

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

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

请参阅示例。

映射到 OR 布尔操作符。

如果在复合查询中仅使用 should 子句,则 compound操作符会将 should 子句查询的大量视为逻辑 OR。MongoDB Search 必须找到至少一个 should 条件的匹配项才能返回任何结果。当您指定多个 should 子句条件并将 minimumShouldMatch 选项设立为 0 时, MongoDB 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 子句中所有子查询的分数之和。 要学习;了解更多信息,请参阅对行为进行评分。

doesNotAffect

要从基于此查询的计数重新计算中排除的分面(Facet)或分面(Facet)列表。值必须是 $search.facets$searchMeta.facets 中定义的分面(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搜索通过文档在文档上生成匹配项的每个子句获得的分数求和,对结果设立进行评分。只有 mustshould 子句参与评分。结果设立按分数从最高到最低排序。

下表显示了影响和不影响分数的 compound子句。

子句
影响分数

filter

must

mustNot

should

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操作符。

以下示例使用 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

➤ 在MongoDB 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 子句。

➤ 在MongoDB 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

➤ 在MongoDB 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 子句中的第一个。

➤ 在MongoDB 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 子句失败,但仍返回文档。

➤ 在MongoDB Search Playground中尝试一下。

在带有 filter 子句的集群数据查询中,您可以将 $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

➤ 在MongoDB 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 子句匹配。

➤ 在MongoDB Search Playground中尝试一下。

以下查询使用 $searchMeta 管道阶段或 $search 阶段的 $$SEARCHMETA 变量检索元数据,以返回 fruit 集合中的类别数。

以下查询仅返回结果中的元数据。

db.fruit.aggregate([
{
"$searchMeta": {
"facet": {
"operator": {
"compound": {
"must": [{
"text": {
"query": "varieties",
"path": "description"
}
}],
"should": [{
"text": {
"query": "Fuji",
"path": "description"
}
}]
}
},
"facets": {
"categoryFacet": {
"type": "string",
"path": "category"
}
}
}
}
}
])
[
{
count: { lowerBound: Long('2') },
facet: {
categoryFacet: {
buckets: [
{ _id: 'nonorganic', count: Long('1') },
{ _id: 'organic', count: Long('1') }
]
}
}
}
]

以下查询返回元数据和搜索结果。

db.fruit.aggregate([
{
"$search": {
"facet": {
"operator": {
"compound": {
"must": [{
"text": {
"query": "varieties",
"path": "description"
}
}],
"should": [{
"text": {
"query": "Fuji",
"path": "description"
}
}]
}
},
"facets": {
"categoryFacet": {
"type": "string",
"path": "category"
}
}
}
}
},
{ "$limit": 2 },
{
"$facet": {
"docs": [
{ "$project":
{
"type": 1,
"description": 1
}
}
],
"meta": [
{"$replaceWith": "$$SEARCH_META"},
{"$limit": 1}
]
}
},
{
"$set": {
"meta": {
"$arrayElemAt": ["$meta", 0]
}
}
}
])
[
{
docs: [
{
_id: 1,
type: 'apple',
description: 'Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.'
},
{
_id: 3,
type: 'pear',
description: 'Bosc and Bartlett are the most common varieties of pears.'
}
],
meta: {
count: { lowerBound: Long('2') },
facet: {
categoryFacet: {
buckets: [
{ _id: 'nonorganic', count: Long('1') },
{ _id: 'organic', count: Long('1') }
]
}
}
}
}
]