compound
For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt
<!-- Tab options on this page. Append to the .md URL to filter: ?tabs=<id,...> select specific tabs (e.g. ?tabs=nodejs,shell) ?allTabs=true include every tab (no param) default: one tab per tabset
Available tabs: other tabs: basic, compoundscore, match, searchmeta-stage, searchmeta-variable -->
compound Operator
Definition
The compound operator combines two or more operators into a single query. Each element of a compound query is called a clause, and each clause consists of one or more sub-queries. MongoDB Search provides a sample compound query template with guidance.
Syntax
compound has the following syntax:
{
$search: {
"index": <index name>, // optional, defaults to "default"
"compound": {
<must | mustNot | should | filter>: [ { <clauses> } ],
"score": <options>,
"doesNotAffect": "<facet-to-exclude>" | [<array-of-facets>]
}
}
}
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](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-compound-examples on this page.
Options
compound uses the following terms to construct a query:
Clauses that must match to for a document to be included in the results. The returned score is the sum of the scores of all the subqueries in the clause. Maps to the AND boolean operator. |
|
|---|---|
Clauses that must not match for a document to be included in the results. mustNot clauses don't contribute to a returned document's score. Maps to the AND NOT boolean operator. |
|
Clauses that you prefer to match in documents that are included in the results. Documents that contain a match for a should clause have higher scores than documents that don't contain a should clause. The returned score is the sum of the scores of all the subqueries in the clause. If you use more than one should clause, you can use the minimumShouldMatch option to specify a minimum number of should clauses that must match to include a document in the results. The value of the minimumShouldMatch must be less than or equal to the number of should clauses in the query. If omitted, the minimumShouldMatch option defaults to 0. See an [example.](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-min-example Maps to the OR boolean operator. If you use only the should clause inside a compound query, the compound operator treats the array of the should clause queries as a logical OR. MongoDB Search must find a match for at least one should criteria to return any results. When you specify multiple should clause criteria with the minimumShouldMatch option set to 0, MongoDB Search treats minimumShouldMatch as set to 1 and must match at least one criteria to return any results. |
|
Clauses that must all match for a document to be included in the results. filter clauses do not contribute to a returned document's score. For example, you can replace the [$match](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match stage with the [$search](https://www.mongodb.com/docs/search/query/aggregation-stages/search.md#mongodb-pipeline-pipe.-search stage using the compound operator filter option. The following [$match](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match stage filters for documents with a given value for the field role: `$match: { |
|
| “role”: { “$in”: [ “CLIENT”, “PROFESSIONAL” ] } | |
}You can use thecompoundoperatorfilteroption instead:$search: { |
|
| “compound”: { | |
| “filter”: [{ | |
| “in”: { | |
| “path”: “role”, | |
| “value”: [ “CLIENT”, “PROFESSIONAL” ] | |
| } | |
| }] | |
| } | |
| }` See another [filter example.](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-filter-example | |
score |
Modify the scoree |
doesNotAffect |
Facet or list of facets to exclude from count recalculation on the basis of this query. Value must be one or more names of a facet defined in $search.facets or $searchMeta.facets. The operator uses the specified facets for filtering documents to match this query, but doesn't recalculate counts for them. For more information, see [Multi-Select Facets.](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-multi-select |
Usage
You can use any of the clauses with any top-level operator, such as [autocomplete](https://www.mongodb.com/docs/search/query/operators-collectors/autocomplete.md#std-label-autocomplete-ref, [text](https://www.mongodb.com/docs/search/query/operators-collectors/text.md#std-label-text-ref, or [span](https://www.mongodb.com/docs/search/query/operators-collectors/span.md#std-label-span-ref, to specify query criteria.
To optimize performance, place non-scoring operators such as [equals](https://www.mongodb.com/docs/search/query/operators-collectors/equals.md#std-label-equals-ref, [range](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref, and [in](https://www.mongodb.com/docs/search/query/operators-collectors/in.md#std-label-in-ref in the [filter](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#mongodb-data-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](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#mongodb-data-should clause within the top-level [filter.](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#mongodb-data-filter
Example:
[
{
$search: {
index: "default",
compound: {
filter: [
{
compound: {
should: [
{
equals: {
path: "accommodates",
value: 2
}
},
{
range: {
path: "pricePerNight",
lte: 200
}
}
]
}
}
]
}
}
}
]
Scoring Behavior
MongoDB Search scores documents in the result set by summing the score that the document received for each individual clause that generated a match on the document. Only must and should clauses participate in scoring. The result set is ordered by score, highest to lowest.
The following table shows the compound clauses that contribute and don't contribute to the score.
| Clause | Contributes to Score |
|---|---|
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](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-must-should-example below. You can use [score](https://www.mongodb.com/docs/search/query/score/overview.md#std-label-scoring-ref 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.](https://www.mongodb.com/docs/search/query/score/modify-score.md#std-label-scoring-options
Examples
You can try the following examples in the MongoDB Search Playground or your cluster.
Sample Collection
To run the [sample queries](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-compound-egs-sample-queries on this page, create a collection named fruit on your cluster and insert the following documents into the collection:
{
"_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
}
Sample Index
To run the [sample queries](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-compound-egs-sample-queries on this page, create the following MongoDB Search index named default on the fruit [sample collection](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-compound-egs-sample-collections. The index definition configures MongoDB Search to do the following:
-
[Dynamically index](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-static-dynamic-mappings all the fiels in the
fruitcollection using the default [standard](https://www.mongodb.com/docs/search/indexes/analyzers/standard.md#std-label-ref-standard-analyzer analyzer to extract tokens. Thestandardanalyzer lower-cases all words and disregards common stop words, such as“the”,“a”,“and”, and so on. -
Statically index the
typefield as the [string](https://www.mongodb.com/docs/search/indexes/field-types/string-type.md#std-label-bson-data-types-string type to support [text](https://www.mongodb.com/docs/search/query/operators-collectors/text.md#std-label-text-ref operator queries and the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token type to support [equals](https://www.mongodb.com/docs/search/query/operators-collectors/equals.md#std-label-equals-ref operator queries.
{
"mappings": {
"dynamic": true,
"fields": {
"type": [
{ "type": "string" },
{ "type": "token" }
]
}
}
}
Sample Queries
The following queries demonstrate the [$search](https://www.mongodb.com/docs/search/query/aggregation-stages/search.md#mongodb-pipeline-pipe.-search compound operator in MongoDB Search queries.
must and mustNot Example
The following example uses a combination of must and mustNot clauses to contruct a query. The must clause uses the [text](https://www.mongodb.com/docs/search/query/operators-collectors/text.md#std-label-text-ref operator to search for the term varieties in the description field. For a document to match, it must fulfill the must clause. The mustNot clause performs a search operation for the term apples in the description field. For a document to match, it must not fulfill the mustNot clause.
db.fruit.aggregate([
{
"$search": {
"compound": {
"must": [{
"text": {
"query": "varieties",
"path": "description"
}
}],
"mustNot": [{
"text": {
"query": "apples",
"path": "description"
}
}]
}
}
}
])
The above query returns the document with _id: 3 because its description field contains the word varieties and does not contain apples.
➤ Try this in the MongoDB Search Playground.
must and should Example
The following queries use must to specify search conditions that must be met and should to specify preference for documents that contain the word Fuji.
Basic Example
For this query, the $project pipeline stage excludes all document fields except _id and adds a score field, which displays the document's relevance score.
db.fruit.aggregate([
{
"$search": {
"compound": {
"must": [{
"text": {
"query": "varieties",
"path": "description"
}
}],
"should": [{
"text": {
"query": "Fuji",
"path": "description"
}
}]
}
}
},
{
"$project": {
"score": { "$meta": "searchScore" }
}
}
])
Output:
{ "_id" : 1, "score" : 0.6425117254257202 }
{ "_id" : 3, "score" : 0.21649497747421265 }
The document with _id: 1 has a higher score because its description field contains the word Fuji, satisfying the should clause.
➤ Try this in the MongoDB Search Playground.
minimumShouldMatch Example
In a query with multiple should clauses, you can use the miniumumShouldMatch option to specify a minimum number of clauses which must match to return a result.
The following query has one must clause and two should clauses, with a minimumShouldMatch value of 1. A document must include the term varieties in the description field and must include either Fuji or Golden Delicious in the description field to be included in the result set.
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
}
}
}
])
Output:
{
"_id" : 1,
"type" : "apple",
"description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.",
"category" : "nonorganic",
"in_stock" : false
}
The document with _id: 1 matches the must clause and the first of the two should clauses.
➤ Try this in the MongoDB Search Playground.
filter Examples
filter behaves the same as must, except that the filter clause is not considered in a returned document's score, and therefore does not affect the order of the returned documents.
Basic Example
The following query uses the following clauses:
-
mustandfilterto specify search conditions which must be met. -
shouldto specify preference for documents containing the wordbanana. Theshouldclause doesn't include theminimumShouldMatchoption. When you omitminimumShouldMatch, it defaults to0.
db.fruit.aggregate([
{
"$search": {
"compound": {
"must": [{
"text": {
"query": "varieties",
"path": "description"
}
}],
"should": [{
"text": {
"query": "banana",
"path": "description"
}
}],
"filter": [{
"text": {
"query": "granny",
"path": "description"
}
}]
}
}
}
])
Output:
{
"_id" : 1,
"type" : "apple",
"description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.",
"category" : "nonorganic",
"in_stock" : false
}
The returned document fulfills all the requirements for inclusion:
-
Both the
mustclause and thefilterclause match. -
The
minimumShouldMatchvalue is not specified, so it defaults to0. As a result, theshouldclause fails and still returns a document.
➤ Try this in the MongoDB Search Playground.
Nested Example
The following example uses nested compound clauses to construct a query. For this example, the fruit collection has an index on the type, category, and in_stock fields, whose text fields use the [default](https://www.mongodb.com/docs/search/indexes/analyzers/standard.md#std-label-ref-standard-analyzer analyzer. The query requires documents to only satisfy one of the following should clauses:
-
Contain the word
applein thetypefield. -
Contain the term
organicin thecategoryfield and have the valuetruein thein_stockfield.
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
}
}
}
])
Output:
{
"_id" : 3,
"type" : "pear",
"description" : "Bosc and Bartlett are the most common varieties of pears.",
"category" : "organic",
"in_stock" : true
}
{
"_id" : 1,
"type" : "apple",
"description" : "Apples come in several varieties, including Fuji, Granny Smith, and Honeycrisp.",
"category" : "nonorganic",
"in_stock" : false
}
The documents in the results fulfill all the requirements for inclusion:
-
The document with
_id: 3matches themustclause nested within the secondshouldclause. -
The document with
_id: 1matches the firstshouldclause.
➤ Try this in the MongoDB Search Playground.
Metadata Examples
The following queries retrieve metadata to return the number of categories in the fruit collection using either the $searchMeta pipeline stage or the $$SEARCHMETA variable of the $search stage.
$searchMeta Stage
The following query returns only the metadata in the results.
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"
}
}
}
}
}
])
Output:
[
{
count: { lowerBound: Long('2') },
facet: {
categoryFacet: {
buckets: [
{ _id: 'nonorganic', count: Long('1') },
{ _id: 'organic', count: Long('1') }
]
}
}
}
]
