对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
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}

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

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": [{
"in": {
"path": "role",
"value": [ "CLIENT", "PROFESSIONAL" ]
}
}]
}
}

请参阅另一过滤示例。

score

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

doesNotAffect

要从基于此查询的计数重新计算中排除的分面(Facet)或分面(Facet)列表。值必须是 $search.facets 或 $searchMeta.facets 中定义的分面(Facet)的一个或多个名称。该操作符符使用指定的分面来筛选文档以匹配此查询,但不会重新计算它们的计数。有关更多信息,请参阅多选分面(Facet)。

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

为优化性能,请将非评分操作符(例如 equals、range 和 in)放入 filter 子句中,避免不必要的评分操作。如果您想运行必须作为 OR 条件求值的操作,请在顶层 filter 中嵌套一个 should子句。

例子

[
{
$search: {
index: "default",
compound: {
filter: [
{
compound: {
should: [
{
equals: {
path: "accommodates",
value: 2
}
},
{
range: {
path: "pricePerNight",
lte: 200
}
}
]
}
}
]
}
}
}
]

MongoDB搜索通过文档在文档上生成匹配项的每个子句获得的分数求和,对结果设立进行评分。只有 must 和 should 子句参与评分。结果设立按分数从最高到最低排序。

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

子句
影响分数

filter

must

mustNot

should

您可以用 score 选项提高或替换整个复合查询的分数。有关替换整个复合分数的示例,请参阅下面的 复合分数示例 。您还可以用分数来提高或更改每个子句中每个子查询的分数。有关 compound 操作符子句中已更改分数的部分示例,请参阅修改分数。

您可以在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 示例集合上创建名为 default 的以下 MongoDB Search 索引。索引定义将 MongoDB Search 配置为执行以下操作:

  • fruit使用默认 标准 分析器提取令牌,动态索引 集合中的所有字段。standard 分析器将所有单词转为小写,并忽略常见的停用词,例如 "the"、"a"、"and"等。

  • 将 type 字段静态索引为 string 类型以支持 text 操作符查询,并索引为 token 类型以支持 equals 操作符查询。

1{
2 "mappings": {
3 "dynamic": true,
4 "fields": {
5 "type": [
6 { "type": "string" },
7 { "type": "token" }
8 ]
9 }
10 }
11}

以下查询演示了MongoDB搜索查询中的$search compound操作符。

以下示例使用 must 和 mustNot 子句的组合来构建查询。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 的文档分数较高,因为其 description 字段包含单词 Fuji,并且满足 should 子句。

➤ 在MongoDB Search Playground中尝试一下。

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

下面的查询有一个 must 子句和两个 should 子句,minimumShouldMatch 值为 1。文档必须在 description 字段中包含术语 varieties,必须在描述字段中包含 Fuji 或 Golden 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])

带有 _id: 1 的文档匹配 must 子句和两个 should 子句中的第一个。

➤ 在MongoDB Search Playground中尝试一下。

filter 其行为与must相同,但返回文档的分数中不考虑filter子句,因此不会影响返回文档的顺序。

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

  • must 和 filter 指定必须满足的搜索条件。

  • 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])

上述文档满足所有包含要求:

  • must 子句和 filter 子句都匹配。

  • 未指定 minimumShouldMatch 值,因此默认为 0。因此,should 子句失败,但仍返回文档。

➤ 在MongoDB Search Playground中尝试一下。

以下示例使用嵌套的 compound 子句构造查询。对于此示例,fruit 集合具有针对 type、category 和 in_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])

结果中的文档满足所有包含要求:

  • _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"
}
}
}
}
}
])