定义
语法
compound 通过以下语法实现:
{ $search: { "index": <index name>, // optional, defaults to "default" "compound": { <must | mustNot | should | filter>: [ { <clauses> } ], "score": <options>, "doesNotAffect": "<facet-to-exclude>" | [<array-of-facets>] } }}每个 must、mustNot、should 和 filter 子句都包含一个子句数组。即使数组只包含一个子句,也仍然使用数组语法。请参阅本页的示例。
选项
compound 使用以下词条来构造查询:
要将文档包含在结果中必须匹配的子句。返回的分数是子句中所有子查询的分数总和。 映射到 | |
要将文档包含在结果中必须不能匹配的子句。 映射到 | |
您希望与结果所包含文档匹配的子句。与不包含 如果使用多个 请参阅示例。 映射到 如果在复合查询中仅使用 | |
要将文档包含在结果中必须全部匹配的子句。 例如,您可以使用 您可以改用 请参阅另一过滤示例。 | |
| |
| 要从基于此查询的计数重新计算中排除的分面(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子句。
子句 | 影响分数 |
|---|---|
| |
| |
| |
|
您可以用 score 选项提高或替换整个复合查询的分数。有关替换整个复合分数的示例,请参阅下面的 复合分数示例 。您还可以用分数来提高或更改每个子句中每个子查询的分数。有关 compound 操作符子句中已更改分数的部分示例,请参阅修改分数。
示例
您可以在MongoDB Search Playground 或集群中尝试以下示例。
样本集合
要在此页面上运行 示例查询,请在集群上创建一个名为 fruit 的集合,并将以下文档插入集合:
{ "_id" : 1, "type" : "apple", "description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.", "category" : "nonorganic", "in_stock" : false},{ "_id" : 2, "type" : "banana", "description" : "Bananas are usually sold in bunches of five or six.", "category" : "nonorganic", "in_stock" : true},{ "_id" : 3, "type" : "pear", "description" : "Bosc and Bartlett are the most common varieties of pears.", "category" : "organic", "in_stock" : true}样本索引
要在此页面上运行 示例查询,请在 fruit 示例集合上创建名为 default 的以下 MongoDB Search 索引。索引定义将 MongoDB Search 配置为执行以下操作:
fruit使用默认 标准 分析器提取令牌,动态索引 集合中的所有字段。standard分析器将所有单词转为小写,并忽略常见的停用词,例如"the"、"a"、"and"等。
{ "mappings": { "dynamic": true, "fields": { "type": [ { "type": "string" }, { "type": "token" } ] } }}样本查询
以下查询演示了MongoDB搜索查询中的$search compound操作符。
must 和 mustNot 示例
以下示例使用 must 和 mustNot 子句的组合来构建查询。must 子句使用文本操作符在 description 字段中搜索术语 varieties。要匹配文档,它必须满足 must 子句。mustNot 子句对 description 字段中的术语 apples 执行搜索操作。要匹配文档,它必须不满足 mustNot 子句。
db.fruit.aggregate([ { "$search": { "compound": { "must": [{ "text": { "query": "varieties", "path": "description" } }], "mustNot": [{ "text": { "query": "apples", "path": "description" } }] } } }])上述查询返回的文档包含 _id: 3,因为其 description 字段包含单词 varieties,而不包含 apples。
➤ 在MongoDB Search Playground中尝试一下。
must 和 should 示例
以下查询使用 must 指定必须满足的搜索条件,使用 should 指定优先搜索包含单词 Fuji 的文档。
对于此查询,$project 管道阶段排除除 _id 之外的所有文档字段,并添加了一个 score 字段,该字段显示文档的相关性分数。
db.fruit.aggregate([ { "$search": { "compound": { "must": [{ "text": { "query": "varieties", "path": "description" } }], "should": [{ "text": { "query": "Fuji", "path": "description" } }] } } }, { "$project": { "score": { "$meta": "searchScore" } } }])包含 _id: 1 的文档分数较高,因为其 description 字段包含单词 Fuji,并且满足 should 子句。
➤ 在MongoDB Search Playground中尝试一下。
以下查询还为结果中的所有文档指定 3 的 constant分数。对于此查询,$project 管道阶段排除了除 _id 之外的所有文档字段,并添加了 score 字段。
db.fruit.aggregate([ { "$search": { "compound": { "must": [{ "text": { "query": "varieties", "path": "description" } }], "should": [{ "text": { "query": "Fuji", "path": "description" } }], "score": { "constant": { "value": 3 } } } } }, { "$project": { "score": { "$meta": "searchScore" } } }])这两个文档获得相同的分数,因为查询中的 constant 选项将结果中每个文档的分数替换为数字 3。
➤ 在MongoDB Search Playground中尝试一下。
minimumShouldMatch 示例
在包含多个 should 子句的查询中,可以使用 miniumumShouldMatch 选项来指定必须匹配才能返回结果的最小子句数。
下面的查询有一个 must 子句和两个 should 子句,minimumShouldMatch 值为 1。文档必须在 description 字段中包含术语 varieties,必须在描述字段中包含 Fuji 或 Golden Delicious,才能被包含在结果集中。
db.fruit.aggregate([ { $search: { "compound": { "must": [{ "text": { "query": "varieties", "path": "description" } }], "should": [{ "text": { "query": "Fuji", "path": "description" } }, { "text": { "query": "Golden Delicious", "path": "description" } }], "minimumShouldMatch": 1 } } }])带有 _id: 1 的文档匹配 must 子句和两个 should 子句中的第一个。
➤ 在MongoDB Search Playground中尝试一下。
filter 示例
filter 其行为与must相同,但返回文档的分数中不考虑filter子句,因此不会影响返回文档的顺序。
以下查询使用了以下子句:
must和filter指定必须满足的搜索条件。should指定包含单词banana的文档的首选项。should子句不包含minimumShouldMatch选项。如果省略minimumShouldMatch,则默认为0。
db.fruit.aggregate([ { "$search": { "compound": { "must": [{ "text": { "query": "varieties", "path": "description" } }], "should": [{ "text": { "query": "banana", "path": "description" } }], "filter": [{ "text": { "query": "granny", "path": "description" } }] } } }])上述文档满足所有包含要求:
must子句和filter子句都匹配。未指定
minimumShouldMatch值,因此默认为0。因此,should子句失败,但仍返回文档。
➤ 在MongoDB Search Playground中尝试一下。
当 $match 阶段跟随 $search 阶段时,您可以通过将匹配条件移动到 $search 阶段内的 filter 子句中来提高查询性能。MongoDB Search 在搜索过程中应用 filter 条件,而不是重新扫描结果集以运行 $match 阶段。
考虑以下管道,它在description 字段中搜索术语 ,然后使用带有varieties $match$in的 仅保留苹果和香蕉:
db.fruit.aggregate([ { "$search": { "text": { "query": "varieties", "path": "description" } } }, { "$match": { "type": { "$in": [ "apple", "banana" ] } } }, { "$project": { "description": 1, "score": { "$meta": "searchScore" } } }])以下查询会将 $match 阶段替换为 filter 子句,该子句在 type 字段上使用 equals 操作符。$search 阶段使用 compound 操作符合并以下子句:
must子句在description字段中匹配varieties搜索术语filter子句匹配apple和banana类型
$project 阶段会执行以下操作:
排除
_id和description之外的所有字段添加一个
score字段,其中包含文档的相关性分数
db.fruit.aggregate([ { "$search": { "compound": { "must": [{ "text": { "query": "varieties", "path": "description" } }], "filter": [{ "in": { "path": "type", "value": [ "apple", "banana" ] } }] } } }, { "$project": { "description": 1, "score": { "$meta": "searchScore" } } }])结果中的文档满足所有包含要求:
两个文档的
type值均为apple或banana,这在查询的filter子句中指定。包含
_id: 1的文档比包含_id: 2的文档得分更高,因为它包含查询 的should子句中指定的术语varieties。
嵌套示例
以下示例使用嵌套的 compound 子句构造查询。对于此示例,fruit 集合具有针对 type、category 和 in_stock 字段的索引,且其文本字段使用默认分析器。此查询要求文档仅满足以下 should 子句之一:
在
type字段中包含单词apple。在
category字段中包含organic一词,并在in_stock字段中使用值true。
db.fruit.aggregate([ { $search: { "compound": { "should": [ { "text": { "query": "apple", "path": "type" } }, { "compound": { "must": [ { "text": { "query": "organic", "path": "category" } }, { "equals": { "value": true, "path": "in_stock" } } ] } } ], "minimumShouldMatch": 1 } } }])结果中的文档满足所有包含要求:
_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" } } } } }])以下查询返回元数据和搜索结果。
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] } } }])