embeddedDocument Operator
For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt
embeddedDocument Operator
Definition
The embeddedDocument operator is similar to [$elemMatch](https://www.mongodb.com/docs/manual/reference/operator/query/elemMatch.md#mongodb-query-op.-elemMatch operator. It constrains multiple query predicates to be satisfied from a single element of an array of embedded documents. embeddedDocument can be used only for queries over fields of the [embeddedDocuments](https://www.mongodb.com/docs/search/indexes/field-types/embedded-documents-type.md#std-label-bson-data-types-embedded-documents type.
Syntax
embeddedDocument has the following syntax:
{
"embeddedDocument": {
"path": "<path-to-field>",
"operator": { <operator-specification> },
"score": { <score-options> }
}
}
Options
embeddedDocument uses the following options to construct a query:
| Field | Type | Description | Necessity |
|---|---|---|---|
operator |
object | Operator to use to query each document in the array of documents that you specify in the path. The [moreLikeThis](https://www.mongodb.com/docs/search/query/operators-collectors/morelikethis.md#std-label-more-like-this-ref operator is not supported. |
Required |
path |
string | Indexed [embeddedDocuments](https://www.mongodb.com/docs/search/indexes/field-types/embedded-documents-type.md#std-label-bson-data-types-embedded-documents type field to search. The specified field must be a parent for all operators and fields specified using the operator option. |
Required |
score |
object | Score to assign to matching search results. You can use the [embedded](https://www.mongodb.com/docs/search/query/score/modify-score.md#std-label-scoring-embedded scoring option to configure scoring options. To learn more, see [Scoring Behavior.](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-query-score |
Optional |
embeddedDocument Operator Limitations
You can't use [highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref in queries inside the embeddedDocument operator.
Note:
MongoDB Search stops replicating changes for indexes larger than 2,100,000,000 index objects per partition, on a replica set or single shard, where each indexed embedded parent document counts as a single object. Surpassing this limit may result in stale query results.
Using the embeddedDocuments field type can result in indexing objects over this index size limit, because each indexed embedded document is counted as a single object. If you create a MongoDB Search index that has or will soon have more than 2.1 billion index objects, use the [numPartitions](https://www.mongodb.com/docs/search/indexes/index-partition.md#std-label-fts-index-partition index option to partition your index (supported only on Search Nodes deployments) or [shard your cluster.](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding
Behavior
When you query embedded documents in arrays using the embeddedDocument operator, MongoDB Search evaluates and scores the operator query predicates at different stages of query execution. MongoDB Search:
-
Evaluates each embedded document in the array independently.
-
Combines the scores of matching results as configured using the
embedded. -
Joins the matching results with the parent document if other query predicates are specified through the [compound.](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-compound-ref
Scoring Behavior
By default, embeddedDocument operator uses the default aggregation strategy, sum, for combining scores of embedded document matches. The embeddedDocument operator score option allows you to override the default and configure the score of matching results using the [embedded](https://www.mongodb.com/docs/search/query/score/modify-score.md#std-label-scoring-embedded option.
See also:
[Score the Documents in the Results](https://www.mongodb.com/docs/search/query/score/overview.md#std-label-scoring-ref
Sorting Behavior
To sort the parent documents by an embedded document field, you must do the following:
-
Index the parents of the embedded document child field as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document type.
-
Index the child field with string values within the embedded document as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token type. For child fields with number and date values, enable [dynamic mapping](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-static-dynamic-mappings to index those fields automatically.
MongoDB Search sorts on parent documents only. It doesn't sort the child fields within an array of documents. For an example, see [Sort Example.](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-query-examples
Faceting Behavior
To facet on only the child documents in an embeddedDocuments array that match your query, add a matching embeddedDocument block to the facet definition, in addition to using embeddedDocument in the query's operator. If you omit the embeddedDocument block on the facet definition, MongoDB Search facets on all child documents in the array, not just the ones that match your query. To learn more, see [Facet on Matching Children of an Embedded Documents Array.](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-embedded-scoped
Highlighting
You can [highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref on fields if the fields are indexed under a parent field of [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document type for query predicates specified inside the embeddedDocument operator. For an example, see [tutorial.](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial
To learn about the embeddedDocument operator limitations, see [embeddedDocument Operator Limitations.](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-query-limitations
Examples
The following examples use the sample_supplies.sales collection in the [sample dataset.](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets
Index Definition
These sample queries use the following index definition on the collection:
{
"mappings": {
"dynamic": true,
"fields": {
"items": [
{
"dynamic": true,
"type": "embeddedDocuments"
},
{
"dynamic": true,
"fields": {
"tags": {
"type": "token"
}
},
"type": "document"
}
],
"purchaseMethod": {
"type": "token"
}
}
}
}
Basic Query
The following query searches the collection for items tagged school with a preference for items named backpack. MongoDB Search scores the results in descending order based on the average (arithmetic mean) score of all matching embedded documents. The query includes a [$limit](https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit.md#mongodb-pipeline-pipe.-limit stage to limit the output to 5 documents and a [$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project stage to:
-
Exclude all fields except
items.nameanditems.tagsfields -
Add a field named
score
db.sales.aggregate({
"$search": {
"embeddedDocument": {
"path": "items",
"operator": {
"compound": {
"must": [{
"text": {
"path": "items.tags",
"query": "school"
}
}],
"should": [{
"text": {
"path": "items.name",
"query": "backpack"
}
}]
}
},
"score": {
"embedded": {
"aggregate": "mean"
}
}
}
}
},
{
$limit: 5
},
{
$project: {
"_id": 0,
"items.name": 1,
"items.tags": 1,
"score": { $meta: "searchScore" }
}
})
Output:
[
{
items: [ {
name: 'backpack',
tags: [ 'school', 'travel', 'kids' ]
} ],
score: 1.2907354831695557
},
{
items: [ {
name: 'envelopes',
tags: [ 'stationary', 'office', 'general' ]
},
{
name: 'printer paper',
tags: [ 'office', 'stationary' ]
},
{
name: 'backpack',
tags: [ 'school', 'travel', 'kids' ]
} ],
score: 1.2907354831695557
},
{
items: [ {
name: 'backpack',
tags: [ 'school', 'travel', 'kids' ]
} ],
score: 1.2907354831695557
},
{
items: [ {
name: 'backpack',
tags: [ 'school', 'travel', 'kids' ]
} ],
score: 1.2907354831695557
},
{
items: [ {
name: 'backpack',
tags: [ 'school', 'travel', 'kids' ]
} ],
score: 1.2907354831695557
}
]
Facet Query
The following query searches for items tagged school with a preference for items named backpack. It requests facet information on the purchaseMethod field.
db.sales.aggregate({
"$searchMeta": {
"facet": {
"operator": {
"embeddedDocument": {
"path": "items",
"operator": {
"compound": {
"must": [
{
"text": {
"path": "items.tags",
"query": "school"
}
}
],
"should": [
{
"text": {
"path": "items.name",
"query": "backpack"
}
}
]
}
}
}
},
"facets": {
"purchaseMethodFacet": {
"type": "string",
"path": "purchaseMethod"
}
}
}
}
})
Output:
[
{
count: { lowerBound: Long("2309") },
facet: {
purchaseMethodFacet: {
buckets: [
{ _id: 'In store', count: Long("2751") },
{ _id: 'Online', count: Long("1535") },
{ _id: 'Phone', count: Long("578") }
]
}
}
}
]
Query and Sort
The following query searches for items named laptop and it sorts the results by the items.tags field. The query includes a [$limit](https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit.md#mongodb-pipeline-pipe.-limit stage to limit the output to 5 documents and a [$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project stage to:
-
Exclude all fields except
items.nameanditems.tags -
Add a field named
score
db.sales.aggregate({
"$search": {
"embeddedDocument": {
"path": "items",
"operator": {
"text": {
"path": "items.name",
"query": "laptop"
}
}
},
"sort": {
"items.tags": 1
}
}
},
{
"$limit": 5
},
{
"$project": {
"_id": 0,
"items.name": 1,
"items.tags": 1,
"score": { "$meta": "searchScore" }
}
})
Output:
[
{
items: [
{ name: 'envelopes', tags: [ 'stationary', 'office', 'general' ] },
{ name: 'binder', tags: [ 'school', 'general', 'organization' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'laptop', tags: [ 'electronics', 'school', 'office' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'printer paper', tags: [ 'office', 'stationary' ] },
{ name: 'backpack', tags: [ 'school', 'travel', 'kids' ] },
{ name: 'pens', tags: [ 'writing', 'office', 'school', 'stationary' ] },
{ name: 'envelopes', tags: [ 'stationary', 'office', 'general' ] }
],
score: 1.168686032295227
},
{
items: [
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'binder', tags: [ 'school', 'general', 'organization' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'pens', tags: [ 'writing', 'office', 'school', 'stationary' ] },
{ name: 'printer paper', tags: [ 'office', 'stationary' ] },
{ name: 'pens', tags: [ 'writing', 'office', 'school', 'stationary' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'backpack', tags: [ 'school', 'travel', 'kids' ] },
{ name: 'laptop', tags: [ 'electronics', 'school', 'office' ] }
],
score: 1.168686032295227
},
{
items: [
{ name: 'backpack', tags: [ 'school', 'travel', 'kids' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'binder', tags: [ 'school', 'general', 'organization' ] },
{ name: 'pens', tags: [ 'writing', 'office', 'school', 'stationary' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'envelopes', tags: [ 'stationary', 'office', 'general' ] },
{ name: 'laptop', tags: [ 'electronics', 'school', 'office' ] }
],
score: 1.168686032295227
},
{
items: [
{ name: 'laptop', tags: [ 'electronics', 'school', 'office' ] },
{ name: 'binder', tags: [ 'school', 'general', 'organization' ] },
{ name: 'binder', tags: [ 'school', 'general', 'organization' ] },
{ name: 'backpack', tags: [ 'school', 'travel', 'kids' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'printer paper', tags: [ 'office', 'stationary' ] },
{ name: 'pens', tags: [ 'writing', 'office', 'school', 'stationary' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'pens', tags: [ 'writing', 'office', 'school', 'stationary' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] }
],
score: 1.168686032295227
},
{
items: [
{ name: 'envelopes', tags: [ 'stationary', 'office', 'general' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'notepad', tags: [ 'office', 'writing', 'school' ] },
{ name: 'backpack', tags: [ 'school', 'travel', 'kids' ] },
{ name: 'envelopes', tags: [ 'stationary', 'office', 'general' ] },
{ name: 'pens', tags: [ 'writing', 'office', 'school', 'stationary' ] },
{ name: 'binder', tags: [ 'school', 'general', 'organization' ] },
{ name: 'laptop', tags: [ 'electronics', 'school', 'office' ] },
{ name: 'printer paper', tags: [ 'office', 'stationary' ] },
{ name: 'binder', tags: [ 'school', 'general', 'organization' ] }
],
score: 1.168686032295227
}
]
Query for Matching Embedded Documents Only
The following query returns only the nested documents that match the query. The query uses MongoDB Search [compound operator](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-compound-ref clauses in the [$search](https://www.mongodb.com/docs/search/query/aggregation-stages/search.md#mongodb-pipeline-pipe.-search stage to find matching documents and then the [aggregation operators](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions in the [$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project stage to return only matching embedded documents. Specifically, the query specifies the following pipeline stages:
[$search](https://www.mongodb.com/docs/search/query/aggregation-stages/search.md#mongodb-pipeline-pipe.-search |
Specifies the following criteria in the [compound operator](https://www.mongodb.com/docs/search/query/operators-collectors/compound.md#std-label-compound-ref must clause: Check if items.price field exists in the collection.; Search for the items tagged as school in the items.tags field.; Match only if value is more than 2 for the items.quantity field. |
|---|---|
[$limit](https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit.md#mongodb-pipeline-pipe.-limit |
Limits the output to 5 documents. |
[$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project |
Perform the following actions: Exclude the _id field and only include the items and storeLocation fields.; Use [$filter](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#mongodb-expression-exp.-filter to return only elements of the items input array that match the condition specified using the [$and](https://www.mongodb.com/docs/manual/reference/operator/aggregation/and.md#mongodb-expression-exp.-and operator. The and operator uses the following operators:[$ifNull](https://www.mongodb.com/docs/manual/reference/operator/aggregation/ifNull.md#mongodb-expression-exp.-ifNull to determine if items.price contains null values and replace null values, if present, with the replacement expression false.; [$gt](https://www.mongodb.com/docs/manual/reference/operator/aggregation/gt.md#mongodb-expression-exp.-gt to check if quantity is greater than 2.; [$in](https://www.mongodb.com/docs/manual/reference/operator/aggregation/in.md#mongodb-expression-exp.-in to check if office exists in the tags array. |
db.sales.aggregate(
{
"$search": {
"embeddedDocument": {
"path": "items",
"operator": {
"compound": {
"must": [
{
"range": {
"path": "items.quantity",
"gt": 2
}
},
{
"exists": {
"path": "items.price"
}
},
{
"text": {
"path": "items.tags",
"query": "school"
}
}
]
}
}
}
}
},
{
"$limit": 2
},
{
"$project": {
"_id": 0,
"storeLocation": 1,
"items": {
"$filter": {
"input": "$items",
"cond": {
"$and": [
{
"$ifNull": [
"$$this.price", "false"
]
},
{
"$gt": [
"$$this.quantity", 2
]
},
{
"$in": [
"office", "$$this.tags"
]
}
]
}
}
}
}
}
)
Output:
[
{
storeLocation: 'Austin',
items: [
{
name: 'laptop',
tags: [ 'electronics', 'school', 'office' ],
price: Decimal128('753.04'),
quantity: 3
},
{
name: 'pens',
tags: [ 'writing', 'office', 'school', 'stationary' ],
price: Decimal128('19.09'),
quantity: 4
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128('30.23'),
quantity: 5
},
{
name: 'pens',
tags: [ 'writing', 'office', 'school', 'stationary' ],
price: Decimal128('20.05'),
quantity: 4
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128('22.08'),
quantity: 3
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128('21.67'),
quantity: 4
}
]
},
{
storeLocation: 'Austin',
items: [
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128('24.16'),
quantity: 5
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128('28.04'),
quantity: 5
},
{
name: 'notepad',
tags: [ 'office', 'writing', 'school' ],
price: Decimal128('21.42'),
quantity: 5
},
{
name: 'laptop',
tags: [ 'electronics', 'school', 'office' ],
price: Decimal128('1540.63'),
quantity: 3
},
{
name: 'pens',
tags: [ 'writing', 'office', 'school', 'stationary' ],
price: Decimal128('29.43'),
quantity: 5
},
{
name: 'pens',
tags: [ 'writing', 'office', 'school', 'stationary' ],
price: Decimal128('28.48'),
quantity: 5
}
]
}
]
Learn More
To learn more, see [How to Run MongoDB Search Queries Against Fields in Embedded Documents.](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial
