> 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: nested-array, nested-within-array, vib, jsonib, jib, cloud, local, maven bom, gradle bom, maven, gradle
-->

# How to Index Fields in Arrays of Objects and Documents

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Retrieve your Service Account access token for the project.

   Use your service account to generate an access token, which authenticates your requests to the Atlas Administration API. To learn how to generate an access token, see [Make an API (Application Programming Interface) Request.](https://www.mongodb.com/docs/atlas/configure-api-access.md#std-label-example-api-request)

2. Make an API (Application Programming Interface) call.

   Replace the following values in the `curl` command below. This command sends a `POST` request to your cluster to create a MongoDB Search index with the `embeddedDocuments` field type.

   - Replace \{`ACCESS-TOKEN`} with the output from the preceding step

   - Replace \{`groupId`} with the project ID of the project where you want to create the MongoDB Search index

   - Replace \{`clusterName`} with the name of the cluster where you want to create the MongoDB Search index

   ```shell
   curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
       --header "Accept: application/vnd.atlas.2025-03-12+json" \
       --header "Content-Type: application/json" \
       -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes" \
       -d '{ "collectionName": "<collection>",
           "database": "<database>",
           "name": "default",
           "type": "search",
           "definition": {
             "mappings": {
               "dynamic": <true|false> | {
                 "typeset" : "<type-set-name>"
               },
               "fields": {
                 "<field-name>": {
                   "type": "embeddedDocuments",
                   "dynamic": <true|false> | {
                     "typeSet": "<type-set-name>"
                   },
                   "fields": {
                     "<field-name>": {
                       <field-mapping-definition>
                     }
                   },
                   "storedSource": <true|false> | {
                     "include" | "exclude": [
                       "<field-name>", 
                       ...
                     ]
                   }
                 },
                 ...
               }
             },
             "typeSets": [
               {
                 "name": "<type-set-name>",
                 "types": [
                   {
                     "type": "<field-type>",
                     ... 
                   },
                   ...
                 ]
               },
               ...
             ]
           }
       }'
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```bash
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Accept: application/vnd.atlas.2025-03-12+json" \
    --header "Content-Type: application/json" \
    -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes" \
    -d '{ "collectionName": "companies",
        "database": "sample_training",
        "name": "default",
        "type": "search",
        "definition": {
            "mappings": { 
              "dynamic": false,
              "fields": { 
                "products": { 
                  "type": "embeddedDocuments",
                  "dynamic": true
                } 
              }
            }
        }
    }'

```

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```bash
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Accept: application/vnd.atlas.2025-03-12+json" \
    --header "Content-Type: application/json" \
    -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes" \
    -d '{ "collectionName": "companies",
        "database": "sample_training",
        "name": "default",
        "type": "search",
        "definition": {
            "mappings": {
              "dynamic": true,
              "fields": {
                "products": {
                  "dynamic": true,
                  "type": "embeddedDocuments"
                },
                "category_code": {
                  "type": "token"
                }
              }
            }
        }
    }'

```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

**Note:**

To configure `typeSet` using the Atlas Administration API for dynamic mappings, you must use API (Application Programming Interface) version 2025-09-10 or higher.

```bash
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Accept: application/vnd.atlas.2025-03-12+json" \
    --header "Content-Type: application/json" \
    -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes" \
    -d '{ "collectionName": "companies",
        "database": "sample_training",
        "name": "default",
        "type": "search",
        "definition": {
          "mappings": {
            "dynamic": false,
            "fields": {
              "relationships": {
                "type": "embeddedDocuments",
                "dynamic": {
                  "typeSet": "stringBooleanIndex"
                },
                "fields": {
                  "person": {
                    "type": "document",
                    "dynamic": {
                      "typeSet": "stringBooleanIndex"
                    }
                  }
                }
              }
            }
          },
          "typeSets": [
            {
              "name": "stringBooleanIndex",
              "types": [
                {
                  "type": "boolean"
                },
                {
                  "type": "string"
                }
              ]
            }
          ]
        }'

```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```bash
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Accept: application/vnd.atlas.2025-03-12+json" \
    --header "Content-Type: application/json" \
    -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes" \
    -d '{ "collectionName": "companies",
        "database": "sample_training",
        "name": "default",
        "type": "search",
        "definition": {
            "mappings": { 
              "fields": { 
                "offices": { 
                  "type": "embeddedDocuments",
                  "dynamic": false,
                  "fields": {
                    "country_code": {
                      "type": "string"
                    },
                    "state_code": {
                      "type": "string"
                    }
                  }
                } 
              }
            }
        }
    }'

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```bash
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Accept: application/vnd.atlas.2025-03-12+json" \
    --header "Content-Type: application/json" \
    -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes" \
    -d '{ "collectionName": "companies",
        "database": "sample_training",
        "name": "default",
        "type": "search",
        "definition": {
          "mappings": { 
            "dynamic": false,
            "fields": { 
              "funding_rounds": { 
                "type": "embeddedDocuments",
                "dynamic": true,
                "storedSource": {
                  "include": ["round_code", "raised_currency_code", "raised_amount"] 
                }
              } 
            }
          }
        }
    }'

```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```bash
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Accept: application/vnd.atlas.2025-03-12+json" \
    --header "Content-Type: application/json" \
    -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes" \
    -d '{ "collectionName": "companies",
        "database": "sample_training",
        "name": "default",
        "type": "search",
        "definition": {
            "mappings": { 
              "dynamic": false,
              "fields": { 
                "products": { 
                  "type": "embeddedDocuments",
                  "dynamic": true,
                  "storedSource": true
                } 
              }
            },
            "storedSource": {
              "include": [ "_id", "name" ]
            }
        }
    }'

```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Create a `search-index.json` configuration file and specify the `embeddedDocuments` type.

   ```json
   {
     "name": "default",
     "collectionName": "<collection>",
     "database": "<database>",
     "definition": {
       "mappings": {
         "dynamic": true|false | {
           "typeSet": "<typeSet-name>"
         },
         "fields": {
           "<field-name>": {
             "type": "embeddedDocuments",
             "dynamic": true|false | {
               "typeSet": "<typeSet-name>"
             },
             "fields": {
               "<field-name>": {
                 <field-mapping-definition>
               }
             },
             "storedSource": true | false | {
               "include" | "exclude": [
                 "<field-name>", 
                 ...
               ]
             }
           }
         }
       },
       "typeSets": [
         {
           "name": "<typeSet-name>",
           "types": [
             {
               "type": "<field-type>",
               ...
             },
             ...
           ]
         },
         ...
       ]
     }
   }
   ```

2. Connect to the Atlas CLI

   In your terminal, connect to your cluster from the Atlas CLI. To learn more, see [Connect from the Atlas CLI.](https://www.mongodb.com/docs/atlas/cli/current/connect-atlas-cli/)

3. Create a MongoDB Search index.

   Run the [atlas clusters search indexes create](https://www.mongodb.com/docs/atlas/cli/current/command/atlas-clusters-search-indexes-create/) command in your terminal, replacing `<clusterName>` with the name of the cluster, and `<path-to-file>` with the path to the `search-index.json` file:

   ```shell
   atlas clusters search indexes create --clusterName <cluster-name> --file <path-to-file>
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```bash
{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "fields": {
        "products": {
          "type": "embeddedDocuments",
          "dynamic": true
        }
      }
    }
  }
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```bash

{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "dynamic": true,
      "fields": {
        "products": {
          "dynamic": true,
          "type": "embeddedDocuments"
        },
        "category_code": {
          "type": "token"
        }
      }
    }
  }
}


```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```bash
{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "dynamic": false,
      "fields": {
        "relationships": {
          "type": "embeddedDocuments",
          "dynamic": {
            "typeSet": "stringBooleanIndex"
          },
          "fields": {
            "person": {
              "type": "document",
              "dynamic": {
                "typeSet": "stringBooleanIndex"
              }
            }
          }
        }
      }
    },
    "typeSets": [
      {
        "name": "stringBooleanIndex",
        "types": [
          {
            "type": "boolean"
          },
          {
            "type": "string"
          }
        ]
      }
    ]
  }
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```bash
{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "fields": {
        "offices": {
          "type": "embeddedDocuments",
          "dynamic": false,
          "fields": {
            "country_code": {
              "type": "string"
            },
            "state_code": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}


```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```bash
{
  "mappings": { 
  "dynamic": false,
  "fields": { 
    "funding_rounds": { 
      "type": "embeddedDocuments",
      "dynamic": true,
      "storedSource": {
        "include": ["round_code", "raised_currency_code", "raised_amount"] 
      }
    } 
  }
}
```

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```bash
{
  "mappings": { 
    "dynamic": false,
    "fields": { 
      "products": { 
        "type": "embeddedDocuments",
        "dynamic": true,
        "storedSource": true
      } 
    }
  },
  "storedSource": {
    "include": [ "_id", "name" ]
  }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Connect to your cluster using MongoDB Compass.

   Open [Compass](https://www.mongodb.com/try/download/compass) and connect to your cluster. For detailed instructions, see [Connect to a Cluster via Compass.](https://www.mongodb.com/docs/atlas/compass-connection.md#std-label-atlas-connect-via-compass)

2. Specify the database and collection.

   On the Database screen, click the name of the database, then click the name of the collection.

3. Create the MongoDB Search index.

   Click the Indexes tab, then select Search Indexes.

   Click Create Atlas Search Index to open the index creation dialog box.

   Specify a name for the index.

   Your MongoDB Search index is named `default` by default. If you keep this name, then your index will be the default Search index for any MongoDB Search query that does not specify a different `index` option in its [operators](https://www.mongodb.com/docs/search/query/operators-collectors/overview.md#std-label-fts-operators). If you are creating multiple indexes, we recommend that you maintain a consistent, descriptive naming convention across your indexes.

   Specify the JSON (Javascript Object Notation) MongoDB Search index definition.

   ```json
   {
     "mappings": {
       "dynamic": true|false {
         "typeSet": "<typeSet-name>"
       },
       "fields": {
         "<field-name>": {
           "type": "embeddedDocuments",
           "dynamic": true|false {
             "typeSet": "<typeSet-name>"
           },
           "fields": {
             "<field-name>": {
               <field-mapping-definition>
             }
           },
           "storedSource": true|false | {
             "include | exclude": {
               "<field-name>", 
               ...
             }
           }
         }
       }
     },
     "typeSets": [
       {
         "name": "<typeSet-name>",
         "types": [
           {
             "type": "<field-type>",
             ...
           },
           ...
         ]
       },
       ...
     ]
   }
   ```

   Click Create Search Index.

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```json
{
  "mappings": {
    "fields": {
      "products": {
        "type": "embeddedDocuments",
        "dynamic": true
      }
    }
  }
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```json
{
  "mappings": {
    "dynamic": true,
    "fields": {
      "products": {
        "dynamic": true,
        "type": "embeddedDocuments"
      },
      "category_code": {
        "type": "token"
      }
    }
  }
}
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```json
{
  "mappings": {
    "dynamic": false,
    "fields": {
      "relationships": {
        "type": "embeddedDocuments",
        "dynamic": {
          "typeSet": "stringBooleanIndex"
        },
        "fields": {
          "person": {
            "type": "document",
            "dynamic": {
              "typeSet": "stringBooleanIndex"
            }
          }
        }
      }
    }
  },
  "typeSets": [
    {
      "name": "stringBooleanIndex",
      "types": [
        {
          "type": "boolean"
        },
        {
          "type": "string"
        }
      ]
    }
  ]
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```json
{
  "mappings": {
    "fields": {
      "offices": {
        "type": "embeddedDocuments",
        "dynamic": false,
        "fields": {
          "country_code": {
            "type": "string"
          },
          "state_code": {
            "type": "string"
          }
        }
      }
    }
  }
}
```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```json
{
  "mappings": { 
    "dynamic": false,
    "fields": { 
      "funding_rounds": { 
        "type": "embeddedDocuments",
        "dynamic": true,
        "storedSource": {
          "include": ["round_code", "raised_currency_code", "raised_amount"] 
        }
      } 
    }
  }
}
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```json
{
  "mappings": { 
    "dynamic": false,
    "fields": { 
      "products": { 
        "type": "embeddedDocuments",
        "dynamic": true,
        "storedSource": true
      } 
    }
  },
  "storedSource": {
    "include": [ "_id", "name" ]
  }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Connect to the deployment by using `mongosh`.

   In your terminal, connect to your Atlas cloud-hosted deployment or local deployment from [`mongosh`](https://www.mongodb.com/docs/mongodb-shell.md#mongodb-binary-bin.mongosh). For detailed instructions on how to connect, see [Connect to a Deployment.](https://www.mongodb.com/docs/mongodb-shell/connect/)

2. Switch to the database that contains the collection for which you want to create the index.

   ```shell
    use <database>
   ```

   **Output:**

   ```shell
   switched to db <database>
   ```

3. Run the `db.collection.createSearchIndex()` method to create the index.

   ```shell
   {
     "name": "default",
     "collectionName": "<collection>",
     "database": "<database>",
     "definition": {
       "mappings": {
         "dynamic": <true|false> | {
           "typeSet": "<typeSet-name>"
         },
         "fields": {
           "<field-name>": {
             "type": "embeddedDocuments",
             "dynamic": <true|false> | {
               "typeSet": "<typeSet-name>"
             },
             "fields": {
               "<field-name>": {
                 <field-mapping-definition>
               }
             },
             "storedSource": <true|false> | {
               "include" | "exclude": [
                 "<field-name>",
                 ...
               ]
             }
           }
         },
         ...
       },
       "typeSets": [
         {
           "name": "<typeSet-name>",
           "types": [
            {
              "type": "<field-type>",
              ...
            },
            ...
           ]
         },
         ...
       ]
     }
   }
   ```

   **Output:**

   ```text
   default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```javascript
db.companies.createSearchIndex(
  "default",
  {
    "mappings": { 
      "dynamic": false,
      "fields": {
        "products": {
          "type": "embeddedDocuments",
          "dynamic": true
        }
      },
      "storedSource": true | false | {
       "include" | "exclude": [
         "<field-name>", 
         ...
       ]
     }
    }
  }
)
```

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```javascript
db.companies.createSearchIndex(
  "default", 
  {
    "mappings": {
      "dynamic": true,
      "fields": {
        "products": {
          "dynamic": true,
          "type": "embeddedDocuments"
        },
        "category_code": {
          "type": "token"
        }
      }
    }
  }
)
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```javascript
db.companies.createSearchIndex(
  "default", 
  "mappings": {
    "dynamic": false,
    "fields": {
      "relationships": {
        "type": "embeddedDocuments",
        "dynamic": {
          "typeSet": "stringBooleanIndex"
        },
        "fields": {
          "person": {
            "type": "document",
            "dynamic": {
              "typeSet": "stringBooleanIndex"
            }
          }
        }
      }
    }
  },
  "typeSets": [
    {
      "name": "personIndex",
      "types": [
        {
          "type": "boolean"
        },
        {
          "type": "string"
        }
      ]
    }
  ]
)
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```javascript
db.companies.createSearchIndex(
  "default", 
  {
    "mappings": {
      "fields": {
        "offices": {
          "type": "embeddedDocuments",
          "dynamic": false,
          "fields": {
            "country_code": {
              "type": "string"
            },
            "state_code": {
              "type": "string"
            }
          }
        }
      }
    }
  }
)

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```javascript
db.companies.createSearchIndex(
  "default",
  {
    "mappings": { 
      "dynamic": false,
      "fields": { 
        "funding_rounds": { 
          "type": "embeddedDocuments",
          "dynamic": true,
          "storedSource": {
            "include": ["round_code", "raised_currency_code", "raised_amount"] 
          }
        } 
      }
    }
  }
)
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```javascript
db.companies.createSearchIndex(
  "default",
  {
    "mappings": { 
      "dynamic": false,
      "fields": { 
        "products": { 
          "type": "embeddedDocuments",
          "dynamic": true,
          "storedSource": true
        } 
      }
    },
    "storedSource": {
      "include": [ "_id", "name" ]
    }
  }
)
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

Choose your preferred configuration method in the Atlas UI and then select the database and collection.

### Visual Editor

1. Click Refine Your Index to configure your index.

2. In the Field Mappings section, click Add
   Field Mapping to open the Add Field Mapping window.

3. Click Customized Configuration.

4. Select the field to index from the Field Name dropdown.

   **Note:**

   You can't index fields that contain the dollar (`$`) sign at the start of the field name.

5. Click the Data Type dropdown and select Embedded Documents.

6. Configure the field properties for the `embeddedDocuments` type. To learn more, see [Field Properties](https://www.mongodb.com/docs/search/indexes/field-types/uuid-type.md#std-label-fts-field-types-uuid-options).

7. Click Add.

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

### Visual Editor

1. In the Add Field Mapping window, select items from the Field Name dropdown.

2. Click the Data Type dropdown and select EmbeddedDocuments.

3. Toggle Enable Dynamic Mapping to enable dynamic mapping, if needed.

4. Click Add.

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

### Visual Editor

Click Add Field in the Field
Mappings section and add the following fields by clicking Add after configuring the settings for each field in the Add
Field Mapping window.

| Field Name | Data Type |
| --- | --- |
| `items` | Click the dropdown and select `EmbeddedDocuments`. |
| `purchaseMethod` | Click the dropdown and select `Token`. |

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

### Visual Editor

You can't configure `typeSets` from the Atlas UI Visual Editor.

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

### Visual Editor

2. In the Add Field Mapping window, select items from the Field Name dropdown.

3. Click the Data Type dropdown and select EmbeddedDocuments.

4. Disable Enable Dynamic Mapping.

5. Click Add.

6. Click Add Embedded Field for the items field in the Field Mappings table and add the following fields by clicking Add after configuring the settings for each field in the Add Embedded Field Mapping window.

   | Field Name | Data Type |
   | --- | --- |
   | items.name | Click the Data Type dropdown and select String. |
   | items.tags | Click the Data Type dropdown and select String. |

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

### Visual Editor

This is not supported in the Atlas UI Visual Editor.

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

### Visual Editor

This is not supported in the Atlas UI Visual Editor.

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up the C project.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` for this project:

   ```shell
   # Create a new directory for the project
   mkdir atlas-search-project && cd atlas-search-project
   ```

   Add the C driver to your project by following the instructions in the [MongoDB C Driver documentation.](https://www.mongodb.com/docs/languages/c/c-driver/current/get-started/)

2. Define the index.

   Create a `create_index.c` file in your project directory, and copy and paste the following code into the file.

   ```c
   #include <mongoc/mongoc.h>
   #include <stdlib.h>

   int main (void)
   {
       mongoc_client_t *client = NULL;
       mongoc_collection_t *collection = NULL;
       mongoc_database_t *database = NULL;
       bson_error_t error;
       bson_t cmd = BSON_INITIALIZER;
       bool ok = true;

       mongoc_init();

       // Connect to your Atlas deployment
       client = mongoc_client_new("<connectionString>");
       if (!client) {
           fprintf(stderr, "Failed to create a MongoDB client.\n");
           ok = false;
           goto cleanup;
       }

       // Access your database and collection
       database = mongoc_client_get_database(client, "<databaseName>");
       collection = mongoc_database_get_collection(database, "<collectionName>");

       // Specify the command and the new index
       const char *cmd_str = BSON_STR({
           "createSearchIndexes" : "<collectionName>",
           "indexes" : [ {
               "name" : "default",
               "definition" : {
                 "mappings": {
                   "dynamic": true, // or false, or { "typeset": "<type-set-name>" }
                   "fields": {
                     "<field-name>": {
                       "type": "embeddedDocuments",
                       "dynamic": true, // or false, or { "typeSet": "<type-set-name>" }
                       "fields": {
                         "<field-name>": {
                           // <field-mapping-definition>
                         }
                       },
                       "storedSource": true // or false, or { "include": ["<field-name>", ...] } or { "exclude": ["<field-name>", ...] }
                     }
                     // ... additional fields
                   }
                 },
                 "typeSets": [
                   {
                     "name": "<type-set-name>",
                     "types": [
                       {
                         "type": "<field-type>"
                         // ... additional field type configuration
                       }
                       // ... additional types
                     ]
                   }
                   // ... additional typeSets
                 ]
               }
           } ]
       });

       // Convert your command to BSON
       if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
           fprintf(stderr, "Failed to parse command: %s\n", error.message);
           ok = false;
           goto cleanup;
       }

       // Create the MongoDB Search index by running the command
       if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
           fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
           ok = false;
           goto cleanup;
       }
       printf ("Index created!\n");

   cleanup:
      mongoc_collection_destroy (collection);
      mongoc_client_destroy (client);
      mongoc_database_destroy (database);
      bson_destroy (&cmd);
      mongoc_cleanup ();
      return ok ? EXIT_SUCCESS : EXIT_FAILURE;
   }
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Set up a CMake application

   To configure your application, create a `CMakeLists.txt` file in your project directory. Then, add the following code to the file:

   ```txt
   cmake_minimum_required(VERSION 3.11)
   project(atlas-search-index LANGUAGES C)
   add_executable (index.out create_index.c)
   find_package(mongoc <version> REQUIRED)
   target_link_libraries(index.out mongoc::mongoc)

   ```

   The preceding code performs the following actions:

   - Configures a C project.

   - Creates a `index.out` executable for your application.

   - Finds and requires the C driver. Replace the `<version>` placeholder with your C driver version embeddedDocuments, such as `2.0.0`.

   - Links the program to the `libmongoc` library.

   **Note:**

   In the sample `CMakeLists.txt` file, the `mongoc::mongoc` target points to either the static library or the shared library. The library type depends on which one is available and whichever type the user specifies in the `MONGOC_DEFAULT_IMPORTED_LIBRARY_TYPE` CMake configuration setting. If you don't set this value and both library types are available, `mongoc::mongoc` uses the static library.

   You can use the `mongoc::static` target to explicitly use the static library or the `mongoc::shared` target to use the shared library.

4. Create the index.

   In your terminal, run the following commands to build and run this application:

   ```shell
   cmake -S. -Bcmake-build
   cmake --build cmake-build --target index.out
   ./cmake-build/index.out
   ```

   **Output:**

   ```text
   Index created!
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": {
                "dynamic": false,
                "fields": {
                  "products": {
                    "type": "embeddedDocuments",
                    "dynamic": true
                  }
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the MongoDB Search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": {
                "dynamic": true,
                "fields": {
                  "products": {
                    "dynamic": true,
                    "type": "embeddedDocuments"
                  },
                  "category_code": {
                    "type": "token"
                  }
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the MongoDB Search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
          "name" : "default",
          "definition" : {
            "mappings": {
              "dynamic": false,
              "fields": {
                "relationships": {
                  "type": "embeddedDocuments",
                  "dynamic": {
                    "typeSet": "stringBooleanIndex"
                  },
                  "fields": {
                    "person": {
                      "type": "document",
                      "dynamic": {
                        "typeSet": "stringBooleanIndex"
                      }
                    }
                  }
                }
              }
            },
            "typeSets": [
              {
                "name": "stringBooleanIndex",
                "types": [
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "string"
                  }
                ]
              }
            ]
          }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the Atlas search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": {
                "fields": {
                  "offices": {
                    "type": "embeddedDocuments",
                    "dynamic": false,
                    "fields": {
                      "country_code": {
                        "type": "string"
                      },
                      "state_code": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the MongoDB Search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": { 
                "dynamic": false,
                "fields": { 
                  "funding_rounds": { 
                    "type": "embeddedDocuments",
                    "dynamic": true,
                    "storedSource": {
                      "include": ["round_code", "raised_currency_code", "raised_amount"] 
                    }
                  } 
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the Atlas search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": { 
                "dynamic": false,
                "fields": { 
                  "products": { 
                    "type": "embeddedDocuments",
                    "dynamic": true,
                    "storedSource": true
                  } 
                }
              },
              "storedSource": {
                "include": [ "_id", "name" ]
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the Atlas search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up and initialize the .NET/C# project.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` and initialize your project in that directory:

   ```shell
   # Create a new directory and initialize the project
   mkdir atlas-search-project && cd atlas-search-project
   dotnet new console

   # Add the MongoDB .NET/C# Driver to your project
   dotnet add package MongoDB.Driver
   ```

   For more detailed installation instructions, see the [MongoDB .NET/C# Driver documentation.](https://www.mongodb.com/docs/drivers/csharp/current/get-started/)

2. Define the index.

   Paste the following code into the `Program.cs` file.

   ```csharp
   using MongoDB.Bson;
   using MongoDB.Driver;

   // Replace the connection string with your MongoDB deployment's connection string
   var uri = "<connection-string>";

   var client = new MongoClient(uri);

   var db = client.GetDatabase("<database>");
   var collection = db.GetCollection<BsonDocument>("<collection>");

   // Create the MongoDB Search index definition for the embeddedDocuments field
   var index =  new CreateSearchIndexModel(
     "default", new BsonDocument
     {
       { "mappings", new BsonDocument
         {
           // "dynamic" can be a boolean or an object with "typeSet" name
           { "dynamic", <true|false> | new BsonDocument { { "typeSet", "<typeSet-name>" } } },
           { "fields", new BsonDocument
             {
               { "<field-name>", new BsonDocument
                 {
                   { "type", "embeddedDocuments" },
                   // "dynamic" can be a boolean or an object with "typeSet" name
                   { "dynamic", <true|false> | new BsonDocument { { "typeSet", "<typeSet-name>" } } },
                   { "fields", new BsonDocument
                     {
                       { "<field-name>", new BsonDocument
                         {
                           // <field-mapping-definition>
                         }
                       }
                       // ... additional fields 
                     }
                   }
                 }
               }
               // ... additional fields 
             }
           }
         }
       },
       { "typeSets", new BsonArray
         {
           new BsonDocument
           {
             { "name", "<typeSet-name>" },
             { "types", new BsonArray
               {
                 new BsonDocument
                 {
                   // <field-type-configuration>
                 }
                 // ... additional types 
               }
             }
           }
           // ... additional typeSets 
         }
       }
     });

   var result = collection.SearchIndexes.CreateOne(index);
   Console.WriteLine($"New index name: {result}");
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   dotnet run Program.cs
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```csharp
using MongoDB.Bson;
using MongoDB.Driver;

// Replace the connection string with your MongoDB deployment's connection string
var uri = "<connection-string>";

var client = new MongoClient(uri);

var db = client.GetDatabase("sample_supplies");
var collection = db.GetCollection<BsonDocument>("sales");

// Create the MongoDB Search index definition for the embeddedDocuments field
var index =  new CreateSearchIndexModel(
  "default", new BsonDocument
  {
    { "mappings", new BsonDocument
      {
        { "dynamic", false },
        { "fields", new BsonDocument
          {
            { "items", new BsonDocument
              {
                { "type", "embeddedDocuments" },
                { "dynamic", true }
              }
            }
          }
        }
      }
    }
  });

var result = collection.SearchIndexes.CreateOne(index);
Console.WriteLine($"New index name: {result}");
```

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```csharp
using MongoDB.Bson;
using MongoDB.Driver;

// Replace the connection string with your MongoDB deployment's connection string
var uri = "<connection-string>";

var client = new MongoClient(uri);

var db = client.GetDatabase("sample_training");
var collection = db.GetCollection<BsonDocument>("companies");

// Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
var index =  new CreateSearchIndexModel(
  "default", new BsonDocument
  {
    { "mappings", new BsonDocument
      {
        { "dynamic", true },
        { "fields", new BsonDocument
          {
            { "products", new BsonDocument
              {
                { "dynamic", true },
                { "type", "embeddedDocuments" }
              }
            },
            { "category_code", new BsonDocument
              {
                { "type", "token" }
              }
            }
          }
        }
      }
    }
  });

var result = collection.SearchIndexes.CreateOne(index);
Console.WriteLine($"New index name: {result}");
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```csharp
using MongoDB.Bson;
using MongoDB.Driver;

// Replace the connection string with your MongoDB deployment's connection string
var uri = "<connection-string>";

var client = new MongoClient(uri);

var db = client.GetDatabase("sample_training");
var collection = db.GetCollection<BsonDocument>("companies");

// Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
var index =  new CreateSearchIndexModel(
  "default", new BsonDocument
  {
    { "mappings", new BsonDocument
      {
        { "fields", new BsonDocument
          {
            { "offices", new BsonDocument
              {
                { "type", "embeddedDocuments" },
                { "dynamic", false },
                { "fields", new BsonDocument
                  {
                    { "country_code", new BsonDocument
                      {
                        { "type", "string" }
                      }
                    },
                    { "state_code", new BsonDocument
                      {
                        { "type", "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  });

var result = collection.SearchIndexes.CreateOne(index);
Console.WriteLine($"New index name: {result}");
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up the C++ project.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` for this project:

   ```shell
   # Create a new directory for the project
   mkdir atlas-search-project && cd atlas-search-project
   ```

   For more detailed installation instructions, see the [MongoDB C++ Driver documentation.](https://www.mongodb.com/docs/languages/cpp/cpp-driver/current/get-started/)

2. Define the index.

   Create a `CreateIndex.cpp` file in your project directory, and copy and paste the following code into the file.

   ```cpp
   #include <iostream>

   #include <bsoncxx/builder/basic/document.hpp>
   #include <bsoncxx/json.hpp>
   #include <mongocxx/client.hpp>
   #include <mongocxx/instance.hpp>
   #include <mongocxx/uri.hpp>

   using bsoncxx::builder::basic::kvp;
   using bsoncxx::builder::basic::make_document;

   int main() {
       // Initialize the MongoDB C++ driver
       mongocxx::instance instance{};

       // Connect to your MongoDB deployment
       mongocxx::uri uri("<connection-string>");
       mongocxx::client client(uri);

       auto db = client["<database>"];
       auto collection = db["<collection>"];
       auto siv = collection.search_indexes();

       // Create the MongoDB Search index definition for the embeddedDocuments field
       auto name = "default";
       auto definition = make_document(
           kvp("mappings", make_document(
               kvp("dynamic", true|false) | make_document(kvp("typeset", "<type-set-name>")),
               kvp("fields", make_document(
                   kvp("<field-name>", make_document(
                       kvp("type", "embeddedDocuments"),
                       kvp("dynamic", true|false) | make_document(kvp("typeset", "<type-set-name>")),
                       kvp("fields", make_document(
                           kvp("<field-name>", make_document(
                               // <field-mapping-definition>
                           )),
                           // ... additional fields
                       )),
                       kvp("storedSource", true|false) | make_document(kvp("include", bsoncxx::builder::basic::array{"<field-name>", ...})) | make_document(kvp("exclude", bsoncxx::builder::basic::array{"<field-name>", ...}))
                   )),
                   // ... additional fields
               ))
           )),
           kvp("typeSets", bsoncxx::builder::basic::array{
               make_document(
                   kvp("name", "<type-set-name>"),
                   kvp("types", bsoncxx::builder::basic::array{
                       make_document(
                           kvp("type", "<field-type>")
                           // ... additional field type configuration
                       )
                       // ... additional types
                   })
               )
               // ... additional typeSets
           })
       );
       auto model = mongocxx::search_index_model(name, definition.view());

       try {
           // Execute the command to create the index
           auto result = siv.create_one(model);
           std::cout << "New index name: " << result << std::endl;
       } catch (const std::exception& e) {
           std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
       }
   }
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   c++ --std=c++17 CreateIndex.cpp $(pkg-config --cflags --libs libmongocxx) -o ./app.out
   ./app.out
   ```

   **Output:**

   ```text
   New index name: default
   ```

   **Tip: MacOS Error**

   MacOS users might see the following error after running the preceding commands:

   ```sh
   dyld[54430]: Library not loaded: @rpath/libmongocxx._noabi.dylib
   ```

   To resolve this error, use the `-Wl`,\`\`-rpath\`\` linker option to set the `@rpath`, as shown in the following code:

   ```sh
   c++ --std=c++17 CreateIndex.cpp -Wl,-rpath,/usr/local/lib/ $(pkg-config --cflags --libs libmongocxx) -o ./app.out
   ./app.out
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the MongoDB Search index definition for the embeddedDocuments field
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("products", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", true)
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", true),
            kvp("fields", make_document(
                kvp("products", make_document(
                    kvp("dynamic", true),
                    kvp("type", "embeddedDocuments")
                )),
                kvp("category_code", make_document(
                    kvp("type", "token")
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }

}
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the Atlas Search index definition for the embeddedDocuments field with dynamic mapping
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("relationships", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", make_document(
                        kvp("typeSet", "stringBooleanIndex")
                    )),
                    kvp("fields", make_document(
                        kvp("person", make_document(
                            kvp("type", "document"),
                            kvp("dynamic", make_document(
                                kvp("typeSet", "stringBooleanIndex")
                            ))
                        ))
                    ))
                ))
            ))
        )),
        kvp("typeSets", []{
            auto arr = bsoncxx::builder::basic::array{};
            arr.append(make_document(
                kvp("name", "stringBooleanIndex"),
                kvp("types", []{
                    auto types_arr = bsoncxx::builder::basic::array{};
                    types_arr.append(make_document(kvp("type", "boolean")));
                    types_arr.append(make_document(kvp("type", "string")));
                    return types_arr;
                }())
            ));
            return arr;
        }())
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }

}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("fields", make_document(
                kvp("offices", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", false),
                    kvp("fields", make_document(
                        kvp("country_code", make_document(
                            kvp("type", "string")
                        )),
                        kvp("state_code", make_document(
                            kvp("type", "string")
                        ))
                    ))
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }

}
```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the Atlas Search index definition for the embeddedDocuments field
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("funding_rounds", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", true),
                    kvp("storedSource", make_document(
                        kvp("include", bsoncxx::builder::basic::array{
                            "round_code", "raised_currency_code", "raised_amount"
                        })
                    ))
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }
}
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the Atlas Search index definition for the embeddedDocuments field
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("products", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", true),
                    kvp("storedSource", true)
                ))
            ))
        )),
        kvp("storedSource", make_document(
            kvp("include", bsoncxx::builder::basic::array{ "_id", "name" })
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up and initialize the Go module.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` and initialize your project in that directory:

   ```shell
   # Create a new directory and initialize the project
   mkdir atlas-search-project && cd atlas-search-project
   go mod init atlas-search-project

   # Add the MongoDB Go Driver to your project
   go get go.mongodb.org/mongo-driver/v2/mongo
   ```

   For more detailed installation instructions, see the [MongoDB Go Driver documentation.](https://www.mongodb.com/docs/drivers/go/current/get-started.md#std-label-go-get-started)

2. Define the index.

   Create a `create_index.go` file in your project directory, and copy and paste the following code into the file.

   ```go
   package main

   import (
   	"context"
   	"fmt"
   	"log"

   	"go.mongodb.org/mongo-driver/v2/bson"
   	"go.mongodb.org/mongo-driver/v2/mongo"
   	"go.mongodb.org/mongo-driver/v2/mongo/options"
   )

   func main() {
   	ctx := context.Background()
   	uri := "<connection-string>"
   	client, err := mongo.Connect(options.Client().
   		ApplyURI(uri))
   	if err != nil {
   		panic(err)
   	}

   	defer func() {
   		if err := client.Disconnect(context.TODO()); err != nil {
   			panic(err)
   		}
   	}()

   	coll := client.Database("<database>").Collection("<collection>")
   	const indexName = "defaultgo"
   	opts := options.SearchIndexes().SetName(indexName).SetType("search")

   	// Define the MongoDB Search index for the embeddedDocuments field
   	searchIndexModel := mongo.SearchIndexModel{
   		Definition: bson.D{
   			{"mappings", bson.D{
   				// "dynamic" can be a boolean or an object with "typeset" name
   				{"dynamic", true}, // or false, or bson.D{{"typeset", "<type-set-name>"}}
   				{"fields", bson.D{
   					{"<field-name>", bson.D{
   						{"type", "embeddedDocuments"},
   						// "dynamic" can be a boolean or an object with "typeSet" name
   						{"dynamic", true}, // or false, or bson.D{{"typeSet", "<type-set-name>"}}
   						{"fields", bson.D{
   							{"<field-name>", bson.D{
   								// <field-mapping-definition>
   							}},
   							// ... additional fields
   						}},
   						{"storedSource", true}, // or false, or bson.D{{"include", bson.A{"<field-name>", /* ... */}}} or bson.D{{"exclude", bson.A{"<field-name>", /* ... */}}}
   					}},
   					// ... additional fields
   				}},
   			}},
   			{"typeSets", bson.A{
   				bson.D{
   					{"name", "<type-set-name>"},
   					{"types", bson.A{
   						bson.D{
   							{"type", "<field-type>"},
   							// ... additional field type configuration
   						},
   						// ... additional types
   					}},
   				},
   				// ... additional typeSets
   			}},
   		},
   		Options: opts,
   	}

   	// Create the index
   	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
   	if err != nil {
   		log.Fatalf("Failed to create the Atlas Search index: %v", err)
   	}

   	fmt.Println("Name of index created: " + searchIndexName)
   }

   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   ### Atlas Cluster

   Your connection string should use the following format:

   ```text
   mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net
   ```

   IMPORTANT: Ensure that your connection string includes your database user's credentials. To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

3. Create the index.

   ```shell
   go run create_index.go
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the MongoDB Search index for the embeddedDocuments field
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"products", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", true},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the MongoDB Search index for the embeddedDocuments field with dynamic mapping
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", true},
				{"fields", bson.D{
					{"products", bson.D{
						{"dynamic", true},
						{"type", "embeddedDocuments"},
					}},
					{"category_code", bson.D{
						{"type", "token"},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the Atlas Search index for the embeddedDocuments field with dynamic mapping
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"relationships", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", bson.D{
							{"typeSet", "stringBooleanIndex"},
						}},
						{"fields", bson.D{
							{"person", bson.D{
								{"type", "document"},
								{"dynamic", bson.D{
									{"typeSet", "stringBooleanIndex"},
								}},
							}},
						}},
					}},
				}},
			}},
			{"typeSets", bson.A{
				bson.D{
					{"name", "stringBooleanIndex"},
					{"types", bson.A{
						bson.D{{"type", "boolean"}},
						bson.D{{"type", "string"}},
					}},
				},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the MongoDB Search index for the embeddedDocuments field with specified fields
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"fields", bson.D{
					{"offices", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", false},
						{"fields", bson.D{
							{"country_code", bson.D{
								{"type", "string"},
							}},
							{"state_code", bson.D{
								{"type", "string"},
							}},
						}},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the Atlas Search index for the embeddedDocuments field
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"funding_rounds", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", true},
						{"storedSource", bson.D{
							{"include", bson.A{"round_code", "raised_currency_code", "raised_amount"}},
						}},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the Atlas Search index for the embeddedDocuments field
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"products", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", true},
						{"storedSource", true},
					}},
				}},
			}},
			{"storedSource", bson.D{
				{"include", bson.A{"_id", "name"}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up your Java project with the MongoDB Java driver.

   In your IDE, create a new [Maven](https://maven.apache.org/) or [Gradle](https://gradle.org/) project. Add the Bill of Materials (BOM) for MongoDB JVM artifacts to your project to organize dependency versions. The BOM simplifies dependency management by ensuring that you maintain consistent and compatible versions of dependencies, such as between the Java driver and the core driver library. Use the BOM to avoid version conflicts and simplify upgrades.

   Select from the following **Maven** and **Gradle** tabs to view instructions for adding the BOM for each dependency manager:

   ### Maven

   Add the following code to the `dependencyManagement` list in your `pom.xml` file:

   ```xml
   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.mongodb</groupId>
               <artifactId>mongodb-driver-bom</artifactId>
               <version>5.5.1</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>
   ```

   To view a list of dependencies that the BOM manages, see the [mongodb-driver-bom dependency listing](https://mvnrepository.com/artifact/org.mongodb/mongodb-driver-bom/5.51) on the Maven Repository website.

   After adding the BOM, select from the following **Maven** and **Gradle** tabs to view instructions for adding the MongoDB Java Sync Driver as a dependency in your project:

   ### Maven

   Add the following code to the `dependencies` array in your Maven project's `pom.xml` file:

   ```xml
   <dependencies>
       <dependency>    
         <groupId>org.mongodb</groupId>    
         <artifactId>mongodb-driver-sync</artifactId>    
         <version>4.11.1</version>    
       </dependency>
   </dependencies>

   ```

   Run your package manager to install the dependencies to your project.

   For more detailed installation instructions and version compatibility, see the [MongoDB Java Driver documentation.](https://www.mongodb.com/docs/drivers/java/sync/current/get-started/)

2. Define the index.

   In your project's base package directory, create a `CreateIndex.java` file and copy and paste the following code into this file.

   ```java
   import com.mongodb.client.*;
   import org.bson.Document;

   public class CreateIndex {
       public static void main(String[] args) {
           // Replace the connection string with your MongoDB deployment's connection string
           String connectionString = "<connection-string>";

           try (MongoClient mongoClient = MongoClients.create(connectionString)) {
               MongoDatabase database = mongoClient.getDatabase("<database>");
               MongoCollection<Document> collection = database.getCollection("<collection>");
               String indexName = "default";

               // Create the MongoDB Search index definition for the embeddedDocuments field
               Document searchIdx = new Document("mappings",
                   new Document("dynamic", true) // or false, or new Document("typeset", "<type-set-name>")
                       .append("fields", new Document(
                           "<field-name>", new Document()
                               .append("type", "embeddedDocuments")
                               .append("dynamic", true) // or false, or new Document("typeSet", "<type-set-name>")
                               .append("fields", new Document(
                                   "<field-name>", new Document()
                                       // <field-mapping-definition>
                               ))
                               .append("storedSource", true) // or false, or new Document("include", java.util.Arrays.asList("<field-name>", ...)) or new Document("exclude", java.util.Arrays.asList("<field-name>", ...))
                           )
                           // ... additional fields
                       ))
               ).append("typeSets",
                   java.util.Arrays.asList(
                       new Document("name", "<type-set-name>")
                           .append("types", java.util.Arrays.asList(
                               new Document("type", "<field-type>")
                                   // ... additional field type configuration
                               // ... additional types
                           ))
                       // ... additional typeSets
                   )
               );
               collection.createSearchIndex(indexName, searchIdx);
               System.out.println("New index name: " + indexName);
           } catch (Exception e) {
               System.err.println("Error creating Atlas Search index: " + e.getMessage());
           }
       }
   }
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Compile and run the file to create the index.

   Compile and run your application in your IDE or your shell.

   ```shell
   javac CreateIndex.java
   java CreateIndex
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```java
import com.mongodb.client.*;
import org.bson.Document;

public class CreateIndex {
    public static void main(String[] args) {
        // Replace the connection string with your MongoDB deployment's connection string
        String connectionString = "<connection-string>";

        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
            MongoDatabase database = mongoClient.getDatabase("sample_training");
            MongoCollection<Document> collection = database.getCollection("companies");
            String indexName = "default";

            // Create the MongoDB Search index definition for the embeddedDocuments field
            Document searchIdx = new Document(
                    "mappings",
                    new Document("dynamic", false)
                            .append("fields",
                                    new Document("products",
                                            new Document("type", "embeddedDocuments")
                                                .append("dynamic", true)))
            );
            collection.createSearchIndex(indexName, searchIdx);
            System.out.println("New index name: " + indexName);
        } catch (Exception e) {
            System.err.println("Error creating Atlas Search index: " + e.getMessage());
        }
    }
}
```

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```java
import com.mongodb.client.*;
import org.bson.Document;

public class CreateIndex {
    public static void main(String[] args) {
        // Replace the connection string with your MongoDB deployment's connection string
        String connectionString = "<connection-string>";

        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
            MongoDatabase database = mongoClient.getDatabase("sample_training");
            MongoCollection<Document> collection = database.getCollection("companies");
            String indexName = "default";

            // Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
            Document searchIdx = new Document(
                    "mappings",
                    new Document("dynamic", true)
                            .append("fields",
                                    new Document("products",
                                            new Document("dynamic", true)
                                                    .append("type", "embeddedDocuments"))
                                            .append("category_code",
                                                    new Document("type", "token")))
            );
            collection.createSearchIndex(indexName, searchIdx);
            System.out.println("New index name: " + indexName);
        } catch (Exception e) {
            System.err.println("Error creating Atlas Search index: " + e.getMessage());
        }
    }
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```java
import com.mongodb.client.*;
import org.bson.Document;

public class CreateIndex {
    public static void main(String[] args) {
        // Replace the connection string with your MongoDB deployment's connection string
        String connectionString = "<connection-string>";

        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
            MongoDatabase database = mongoClient.getDatabase("sample_training");
            MongoCollection<Document> collection = database.getCollection("companies");
            String indexName = "default";

            // Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
            Document searchIdx = new Document(
                    "mappings",
                    new Document("fields",
                            new Document("offices",
                                    new Document("type", "embeddedDocuments")
                                            .append("dynamic", false)
                                            .append("fields",
                                                    new Document("country_code", new Document("type", "string"))
                                                            .append("state_code", new Document("type", "string")))))
            );
            collection.createSearchIndex(indexName, searchIdx);
            System.out.println("New index name: " + indexName);
        } catch (Exception e) {
            System.err.println("Error creating Atlas Search index: " + e.getMessage());
        }
    }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Initialize your Node.js project.

   ```shell
   # Create a new directory and initialize the project
   mkdir atlas-search-project && cd atlas-search-project
   npm init -y

   # Add the MongoDB Node.js Driver to your project
   npm install mongodb
   ```

   For detailed installation instructions, see the [MongoDB Node Driver documentation.](https://www.mongodb.com/docs/drivers/node/current/)

2. Define the index.

   Create a `create-index.js` file in your project directory, and copy and paste the following code into the file.

   ```javascript
   const { MongoClient } = require("mongodb");

   // Replace the connection string with your MongoDB deployment's connection string
   const uri =  "<connection-string>";

   const client = new MongoClient(uri);

   async function run() {
     try {
       const database = client.db("<database>");
       const collection = database.collection("<collection>");

       // Create the MongoDB Search index definition for the embeddedDocuments field
       const index = {
           name: "default",
           definition: {
             "mappings": {
               "dynamic": true, // or false, or { "typeset": "<type-set-name>" }
               "fields": {
                 "<field-name>": {
                   "type": "embeddedDocuments",
                   "dynamic": true, // or false, or { "typeSet": "<type-set-name>" }
                   "fields": {
                     "<field-name>": {
                       // <field-mapping-definition>
                     }
                   },
                   "storedSource": true // or false, or { "include": ["<field-name>", ...] } or { "exclude": ["<field-name>", ...] }
                 }
                 // ... additional fields
               }
             },
             "typeSets": [
               {
                 "name": "<type-set-name>",
                 "types": [
                   {
                     "type": "<field-type>"
                     // ... additional field type configuration
                   }
                   // ... additional types
                 ]
               }
               // ... additional typeSets
             ]
           }
       }

       // Create the index
       const result = await collection.createSearchIndex(index);
       console.log("New index name: " + result);
     } finally {
       await client.close();
     }
   }

   run().catch(console.dir);

   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   node create-index.js
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the MongoDB Search index definition for the embeddedDocuments field
    const index = {
        name: "default",
        definition: {
            "mappings": {
                "dynamic": false,
                "fields": {
                    "products": {
                        "type": "embeddedDocuments",
                        "dynamic": true
                    }
                }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
    const index = {
        name: "default",
        definition: {
            "mappings": {
                "dynamic": true,
                "fields": {
                    "products": {
                        "dynamic": true,
                        "type": "embeddedDocuments"
                    },
                    "category_code": {
                        "type": "token"
                    }
                }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the Atlas Search index definition for the embeddedDocuments field with dynamic mapping
    const index = {
        name: "default",
        definition: {
          "mappings": {
            "dynamic": false,
            "fields": {
              "relationships": {
                "type": "embeddedDocuments",
                "dynamic": {
                  "typeSet": "stringBooleanIndex"
                },
                "fields": {
                  "person": {
                    "type": "document",
                    "dynamic": {
                      "typeSet": "stringBooleanIndex"
                    }
                  }
                }
              }
            }
          },
          "typeSets": [
            {
              "name": "stringBooleanIndex",
              "types": [
                {
                  "type": "boolean"
                },
                {
                  "type": "string"
                }
              ]
            }
          ]
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
    const index = {
        name: "default",
        definition: {
            "mappings": {
                "fields": {
                    "offices": {
                        "type": "embeddedDocuments",
                        "dynamic": false,
                        "fields": {
                            "country_code": {
                                "type": "string"
                            },
                            "state_code": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the Atlas Search index definition for the embeddedDocuments field
    const index = {
        name: "default",
        definition: {
            "mappings": { 
              "dynamic": false,
              "fields": { 
                "funding_rounds": { 
                  "type": "embeddedDocuments",
                  "dynamic": true,
                  "storedSource": {
                    "include": ["round_code", "raised_currency_code", "raised_amount"] 
                  }
                } 
              }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the Atlas Search index definition for the embeddedDocuments field
    const index = {
        name: "default",
        definition: {
          "mappings": { 
            "dynamic": false,
            "fields": { 
              "products": { 
                "type": "embeddedDocuments",
                "dynamic": true,
                "storedSource": true
              } 
            }
          },
          "storedSource": {
            "include": [ "_id", "name" ]
          }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up the Python project.

   ```shell
   # Create a new directory for the project
   mkdir atlas-search-project && cd atlas-search-project

   # Install PyMongo
   pip install pymongo
   ```

   For detailed installation instructions, see [MongoDB Python Driver (PyMongo).](https://www.mongodb.com/docs/languages/python/pymongo-driver/get-started.md#std-label-pymongo-get-started-download-and-install)

2. Define the index.

   Create a `create_index.py` file in your project directory, and copy and paste the following code into the file.

   ```python
   from pymongo import MongoClient
   from pymongo.operations import SearchIndexModel

   # Connect to your Atlas deployment
   uri = "<connection-string>"
   client = MongoClient(uri)

   database = client["<database>"]
   collection = database["<collection>"]

   # Create the MongoDB Search index definition for the embeddedDocuments field
   search_index_model = SearchIndexModel(
       definition={
           "mappings": {
             "dynamic": <True|False> | {
               "typeSet": "<typeSet-name>"
             },
             "fields": {
               "<field-name>": {
                 "type": "embeddedDocuments",
                 "dynamic": <True|False> | {
                   "typeSet": "<typeSet-name>"
                 },
                 "fields": {
                   "<field-name>": {
                     <field-mapping-definition>
                   }
                 },
                 "storedSource": <True|False>  | {"include" | "exclude": ["<field-name>", ...]}
               },
               ...
             }
           },
           "typeSets": [
             {
               "name": "<typeSet-name>",
               "types": [
                 {
                   "type": "<field-type>",
                   ... 
                 },
                 ...
               ]
             },
             ...
           ]
       },
       name="default",
   )

   # Create the index
   result = collection.create_search_index(model=search_index_model)
   print(f"New index name: {result}")

   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   python create_index.py
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the MongoDB Search index definition for the embeddedDocuments field
search_index_model = SearchIndexModel(
    definition={
        "mappings": {
            "dynamic": False,
            "fields": {
                "products":{
                   "type": "embeddedDocuments",
                   "dynamic": True
                }
            }
        },
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
search_index_model = SearchIndexModel(
    definition={
        "mappings": {
            "dynamic": True,
            "fields": {
                "products": {
                    "dynamic": True,
                    "type": "embeddedDocuments"
                },
                "category_code": {
                    "type": "token"
                }
            }
        },
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the Atlas Search index definition for the embeddedDocuments field with dynamic mapping
search_index_model = SearchIndexModel(
    definition={
      "mappings": {
        "dynamic": false,
        "fields": {
          "relationships": {
            "type": "embeddedDocuments",
            "dynamic": {
              "typeSet": "stringBooleanIndex"
            },
            "fields": {
              "person": {
                "type": "document",
                "dynamic": {
                  "typeSet": "stringBooleanIndex"
                }
              }
            }
          }
        }
      },
      "typeSets": [
        {
          "name": "stringBooleanIndex",
          "types": [
            {
              "type": "boolean"
            },
            {
              "type": "string"
            }
          ]
        }
      ]
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
search_index_model = SearchIndexModel(
    definition={
        "mappings": {
            "fields": {
                "offices": {
                    "type": "embeddedDocuments",
                    "dynamic": False,
                    "fields": {
                        "country_code": {
                            "type": "string"
                        },
                        "state_code": {
                            "type": "string"
                        }
                    }
                }
            }
        },
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the Atlas Search index definition for the embeddedDocuments field
search_index_model = SearchIndexModel(
    definition={
        "mappings": { 
          "dynamic": false,
            "fields": { 
            "funding_rounds": { 
              "type": "embeddedDocuments",
              "dynamic": true,
              "storedSource": {
                "include": ["round_code", "raised_currency_code", "raised_amount"] 
              }
            } 
          }
        }
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```text
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the Atlas Search index definition for the embeddedDocuments field
search_index_model = SearchIndexModel(
    definition={
        "mappings": { 
          "dynamic": false,
          "fields": { 
            "products": { 
              "type": "embeddedDocuments",
              "dynamic": true,
              "storedSource": true
            } 
          }
        },
        "storedSource": {
          "include": [ "_id", "name" ]
        }
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Create a `search-index.json` configuration file and specify the `embeddedDocuments` type.

   ```json
   {
     "name": "default",
     "collectionName": "<collection>",
     "database": "<database>",
     "definition": {
       "mappings": {
         "dynamic": true|false | {
           "typeSet": "<typeSet-name>"
         },
         "fields": {
           "<field-name>": {
             "type": "embeddedDocuments",
             "dynamic": true|false | {
               "typeSet": "<typeSet-name>"
             },
             "fields": {
               "<field-name>": {
                 <field-mapping-definition>
               }
             },
             "storedSource": true | false | {
               "include" | "exclude": [
                 "<field-name>", 
                 ...
               ]
             }
           }
         }
       },
       "typeSets": [
         {
           "name": "<typeSet-name>",
           "types": [
             {
               "type": "<field-type>",
               ...
             },
             ...
           ]
         },
         ...
       ]
     }
   }
   ```

2. Connect to the Atlas CLI

   In your terminal, connect to your local deployment from the Atlas CLI. To learn more, see [Connect from the Atlas CLI.](https://www.mongodb.com/docs/atlas/cli/current/connect-atlas-cli/)

3. Create a MongoDB Search index.

   Run the [atlas deployments search indexes create](https://www.mongodb.com/docs/atlas/cli/current/command/atlas-deployments-search-indexes-create/) command in your terminal, replacing `<path-to-file>` with the path to the `search-index.json` file:

   ```shell
   atlas deployments search indexes create --file <path-to-file>
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```bash
{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "fields": {
        "products": {
          "type": "embeddedDocuments",
          "dynamic": true
        }
      }
    }
  }
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```bash

{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "dynamic": true,
      "fields": {
        "products": {
          "dynamic": true,
          "type": "embeddedDocuments"
        },
        "category_code": {
          "type": "token"
        }
      }
    }
  }
}


```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```bash
{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "dynamic": false,
      "fields": {
        "relationships": {
          "type": "embeddedDocuments",
          "dynamic": {
            "typeSet": "stringBooleanIndex"
          },
          "fields": {
            "person": {
              "type": "document",
              "dynamic": {
                "typeSet": "stringBooleanIndex"
              }
            }
          }
        }
      }
    },
    "typeSets": [
      {
        "name": "stringBooleanIndex",
        "types": [
          {
            "type": "boolean"
          },
          {
            "type": "string"
          }
        ]
      }
    ]
  }
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```bash
{
  "name": "default",
  "collectionName": "companies",
  "database": "sample_training",
  "type": "search",
  "definition": {
    "mappings": {
      "fields": {
        "offices": {
          "type": "embeddedDocuments",
          "dynamic": false,
          "fields": {
            "country_code": {
              "type": "string"
            },
            "state_code": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}


```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```bash
{
  "mappings": { 
  "dynamic": false,
  "fields": { 
    "funding_rounds": { 
      "type": "embeddedDocuments",
      "dynamic": true,
      "storedSource": {
        "include": ["round_code", "raised_currency_code", "raised_amount"] 
      }
    } 
  }
}
```

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```bash
{
  "mappings": { 
    "dynamic": false,
    "fields": { 
      "products": { 
        "type": "embeddedDocuments",
        "dynamic": true,
        "storedSource": true
      } 
    }
  },
  "storedSource": {
    "include": [ "_id", "name" ]
  }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Connect to your cluster using MongoDB Compass.

   Open [Compass](https://www.mongodb.com/try/download/compass) and connect to your cluster. For detailed instructions, see [Connect to a Cluster via Compass.](https://www.mongodb.com/docs/atlas/compass-connection.md#std-label-atlas-connect-via-compass)

2. Specify the database and collection.

   On the Database screen, click the name of the database, then click the name of the collection.

3. Create the MongoDB Search index.

   Click the Indexes tab, then select Search Indexes.

   Click Create Atlas Search Index to open the index creation dialog box.

   Specify a name for the index.

   Your MongoDB Search index is named `default` by default. If you keep this name, then your index will be the default Search index for any MongoDB Search query that does not specify a different `index` option in its [operators](https://www.mongodb.com/docs/search/query/operators-collectors/overview.md#std-label-fts-operators). If you are creating multiple indexes, we recommend that you maintain a consistent, descriptive naming convention across your indexes.

   Specify the JSON (Javascript Object Notation) MongoDB Search index definition.

   ```json
   {
     "mappings": {
       "dynamic": true|false {
         "typeSet": "<typeSet-name>"
       },
       "fields": {
         "<field-name>": {
           "type": "embeddedDocuments",
           "dynamic": true|false {
             "typeSet": "<typeSet-name>"
           },
           "fields": {
             "<field-name>": {
               <field-mapping-definition>
             }
           },
           "storedSource": true|false | {
             "include | exclude": {
               "<field-name>", 
               ...
             }
           }
         }
       }
     },
     "typeSets": [
       {
         "name": "<typeSet-name>",
         "types": [
           {
             "type": "<field-type>",
             ...
           },
           ...
         ]
       },
       ...
     ]
   }
   ```

   Click Create Search Index.

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```json
{
  "mappings": {
    "fields": {
      "products": {
        "type": "embeddedDocuments",
        "dynamic": true
      }
    }
  }
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```json
{
  "mappings": {
    "dynamic": true,
    "fields": {
      "products": {
        "dynamic": true,
        "type": "embeddedDocuments"
      },
      "category_code": {
        "type": "token"
      }
    }
  }
}
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```json
{
  "mappings": {
    "dynamic": false,
    "fields": {
      "relationships": {
        "type": "embeddedDocuments",
        "dynamic": {
          "typeSet": "stringBooleanIndex"
        },
        "fields": {
          "person": {
            "type": "document",
            "dynamic": {
              "typeSet": "stringBooleanIndex"
            }
          }
        }
      }
    }
  },
  "typeSets": [
    {
      "name": "stringBooleanIndex",
      "types": [
        {
          "type": "boolean"
        },
        {
          "type": "string"
        }
      ]
    }
  ]
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```json
{
  "mappings": {
    "fields": {
      "offices": {
        "type": "embeddedDocuments",
        "dynamic": false,
        "fields": {
          "country_code": {
            "type": "string"
          },
          "state_code": {
            "type": "string"
          }
        }
      }
    }
  }
}
```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```json
{
  "mappings": { 
    "dynamic": false,
    "fields": { 
      "funding_rounds": { 
        "type": "embeddedDocuments",
        "dynamic": true,
        "storedSource": {
          "include": ["round_code", "raised_currency_code", "raised_amount"] 
        }
      } 
    }
  }
}
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```json
{
  "mappings": { 
    "dynamic": false,
    "fields": { 
      "products": { 
        "type": "embeddedDocuments",
        "dynamic": true,
        "storedSource": true
      } 
    }
  },
  "storedSource": {
    "include": [ "_id", "name" ]
  }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Connect to the deployment by using `mongosh`.

   In your terminal, connect to your Atlas cloud-hosted deployment or local deployment from [`mongosh`](https://www.mongodb.com/docs/mongodb-shell.md#mongodb-binary-bin.mongosh). For detailed instructions on how to connect, see [Connect to a Deployment.](https://www.mongodb.com/docs/mongodb-shell/connect/)

2. Switch to the database that contains the collection for which you want to create the index.

   ```shell
    use <database>
   ```

   **Output:**

   ```shell
   switched to db <database>
   ```

3. Run the `db.collection.createSearchIndex()` method to create the index.

   ```shell
   {
     "name": "default",
     "collectionName": "<collection>",
     "database": "<database>",
     "definition": {
       "mappings": {
         "dynamic": <true|false> | {
           "typeSet": "<typeSet-name>"
         },
         "fields": {
           "<field-name>": {
             "type": "embeddedDocuments",
             "dynamic": <true|false> | {
               "typeSet": "<typeSet-name>"
             },
             "fields": {
               "<field-name>": {
                 <field-mapping-definition>
               }
             },
             "storedSource": <true|false> | {
               "include" | "exclude": [
                 "<field-name>",
                 ...
               ]
             }
           }
         },
         ...
       },
       "typeSets": [
         {
           "name": "<typeSet-name>",
           "types": [
            {
              "type": "<field-type>",
              ...
            },
            ...
           ]
         },
         ...
       ]
     }
   }
   ```

   **Output:**

   ```text
   default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```javascript
db.companies.createSearchIndex(
  "default",
  {
    "mappings": { 
      "dynamic": false,
      "fields": {
        "products": {
          "type": "embeddedDocuments",
          "dynamic": true
        }
      },
      "storedSource": true | false | {
       "include" | "exclude": [
         "<field-name>", 
         ...
       ]
     }
    }
  }
)
```

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```javascript
db.companies.createSearchIndex(
  "default", 
  {
    "mappings": {
      "dynamic": true,
      "fields": {
        "products": {
          "dynamic": true,
          "type": "embeddedDocuments"
        },
        "category_code": {
          "type": "token"
        }
      }
    }
  }
)
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```javascript
db.companies.createSearchIndex(
  "default", 
  "mappings": {
    "dynamic": false,
    "fields": {
      "relationships": {
        "type": "embeddedDocuments",
        "dynamic": {
          "typeSet": "stringBooleanIndex"
        },
        "fields": {
          "person": {
            "type": "document",
            "dynamic": {
              "typeSet": "stringBooleanIndex"
            }
          }
        }
      }
    }
  },
  "typeSets": [
    {
      "name": "personIndex",
      "types": [
        {
          "type": "boolean"
        },
        {
          "type": "string"
        }
      ]
    }
  ]
)
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```javascript
db.companies.createSearchIndex(
  "default", 
  {
    "mappings": {
      "fields": {
        "offices": {
          "type": "embeddedDocuments",
          "dynamic": false,
          "fields": {
            "country_code": {
              "type": "string"
            },
            "state_code": {
              "type": "string"
            }
          }
        }
      }
    }
  }
)

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```javascript
db.companies.createSearchIndex(
  "default",
  {
    "mappings": { 
      "dynamic": false,
      "fields": { 
        "funding_rounds": { 
          "type": "embeddedDocuments",
          "dynamic": true,
          "storedSource": {
            "include": ["round_code", "raised_currency_code", "raised_amount"] 
          }
        } 
      }
    }
  }
)
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```javascript
db.companies.createSearchIndex(
  "default",
  {
    "mappings": { 
      "dynamic": false,
      "fields": { 
        "products": { 
          "type": "embeddedDocuments",
          "dynamic": true,
          "storedSource": true
        } 
      }
    },
    "storedSource": {
      "include": [ "_id", "name" ]
    }
  }
)
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up the C project.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` for this project:

   ```shell
   # Create a new directory for the project
   mkdir atlas-search-project && cd atlas-search-project
   ```

   Add the C driver to your project by following the instructions in the [MongoDB C Driver documentation.](https://www.mongodb.com/docs/languages/c/c-driver/current/get-started/)

2. Define the index.

   Create a `create_index.c` file in your project directory, and copy and paste the following code into the file.

   ```c
   #include <mongoc/mongoc.h>
   #include <stdlib.h>

   int main (void)
   {
       mongoc_client_t *client = NULL;
       mongoc_collection_t *collection = NULL;
       mongoc_database_t *database = NULL;
       bson_error_t error;
       bson_t cmd = BSON_INITIALIZER;
       bool ok = true;

       mongoc_init();

       // Connect to your Atlas deployment
       client = mongoc_client_new("<connectionString>");
       if (!client) {
           fprintf(stderr, "Failed to create a MongoDB client.\n");
           ok = false;
           goto cleanup;
       }

       // Access your database and collection
       database = mongoc_client_get_database(client, "<databaseName>");
       collection = mongoc_database_get_collection(database, "<collectionName>");

       // Specify the command and the new index
       const char *cmd_str = BSON_STR({
           "createSearchIndexes" : "<collectionName>",
           "indexes" : [ {
               "name" : "default",
               "definition" : {
                 "mappings": {
                   "dynamic": true, // or false, or { "typeset": "<type-set-name>" }
                   "fields": {
                     "<field-name>": {
                       "type": "embeddedDocuments",
                       "dynamic": true, // or false, or { "typeSet": "<type-set-name>" }
                       "fields": {
                         "<field-name>": {
                           // <field-mapping-definition>
                         }
                       },
                       "storedSource": true // or false, or { "include": ["<field-name>", ...] } or { "exclude": ["<field-name>", ...] }
                     }
                     // ... additional fields
                   }
                 },
                 "typeSets": [
                   {
                     "name": "<type-set-name>",
                     "types": [
                       {
                         "type": "<field-type>"
                         // ... additional field type configuration
                       }
                       // ... additional types
                     ]
                   }
                   // ... additional typeSets
                 ]
               }
           } ]
       });

       // Convert your command to BSON
       if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
           fprintf(stderr, "Failed to parse command: %s\n", error.message);
           ok = false;
           goto cleanup;
       }

       // Create the MongoDB Search index by running the command
       if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
           fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
           ok = false;
           goto cleanup;
       }
       printf ("Index created!\n");

   cleanup:
      mongoc_collection_destroy (collection);
      mongoc_client_destroy (client);
      mongoc_database_destroy (database);
      bson_destroy (&cmd);
      mongoc_cleanup ();
      return ok ? EXIT_SUCCESS : EXIT_FAILURE;
   }
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Set up a CMake application

   To configure your application, create a `CMakeLists.txt` file in your project directory. Then, add the following code to the file:

   ```txt
   cmake_minimum_required(VERSION 3.11)
   project(atlas-search-index LANGUAGES C)
   add_executable (index.out create_index.c)
   find_package(mongoc <version> REQUIRED)
   target_link_libraries(index.out mongoc::mongoc)

   ```

   The preceding code performs the following actions:

   - Configures a C project.

   - Creates a `index.out` executable for your application.

   - Finds and requires the C driver. Replace the `<version>` placeholder with your C driver version embeddedDocuments, such as `2.0.0`.

   - Links the program to the `libmongoc` library.

   **Note:**

   In the sample `CMakeLists.txt` file, the `mongoc::mongoc` target points to either the static library or the shared library. The library type depends on which one is available and whichever type the user specifies in the `MONGOC_DEFAULT_IMPORTED_LIBRARY_TYPE` CMake configuration setting. If you don't set this value and both library types are available, `mongoc::mongoc` uses the static library.

   You can use the `mongoc::static` target to explicitly use the static library or the `mongoc::shared` target to use the shared library.

4. Create the index.

   In your terminal, run the following commands to build and run this application:

   ```shell
   cmake -S. -Bcmake-build
   cmake --build cmake-build --target index.out
   ./cmake-build/index.out
   ```

   **Output:**

   ```text
   Index created!
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": {
                "dynamic": false,
                "fields": {
                  "products": {
                    "type": "embeddedDocuments",
                    "dynamic": true
                  }
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the MongoDB Search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": {
                "dynamic": true,
                "fields": {
                  "products": {
                    "dynamic": true,
                    "type": "embeddedDocuments"
                  },
                  "category_code": {
                    "type": "token"
                  }
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the MongoDB Search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
          "name" : "default",
          "definition" : {
            "mappings": {
              "dynamic": false,
              "fields": {
                "relationships": {
                  "type": "embeddedDocuments",
                  "dynamic": {
                    "typeSet": "stringBooleanIndex"
                  },
                  "fields": {
                    "person": {
                      "type": "document",
                      "dynamic": {
                        "typeSet": "stringBooleanIndex"
                      }
                    }
                  }
                }
              }
            },
            "typeSets": [
              {
                "name": "stringBooleanIndex",
                "types": [
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "string"
                  }
                ]
              }
            ]
          }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the Atlas search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": {
                "fields": {
                  "offices": {
                    "type": "embeddedDocuments",
                    "dynamic": false,
                    "fields": {
                      "country_code": {
                        "type": "string"
                      },
                      "state_code": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the MongoDB Search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": { 
                "dynamic": false,
                "fields": { 
                  "funding_rounds": { 
                    "type": "embeddedDocuments",
                    "dynamic": true,
                    "storedSource": {
                      "include": ["round_code", "raised_currency_code", "raised_amount"] 
                    }
                  } 
                }
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the Atlas search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```c
#include <mongoc/mongoc.h>
#include <stdlib.h>

int main (void)
{
    mongoc_client_t *client = NULL;
    mongoc_collection_t *collection = NULL;
    mongoc_database_t *database = NULL;
    bson_error_t error;
    bson_t cmd = BSON_INITIALIZER;
    bool ok = true;

    mongoc_init();

    // Connect to your Atlas deployment
    client = mongoc_client_new("<connectionString>");
    if (!client) {
        fprintf(stderr, "Failed to create a MongoDB client.\n");
        ok = false;
        goto cleanup;
    }

    // Access your database and collection
    database = mongoc_client_get_database(client, "sample_training");
    collection = mongoc_database_get_collection(database, "companies");

    // Specify the command and the new index
    const char *cmd_str = BSON_STR({
        "createSearchIndexes" : collection,
        "indexes" : [ {
            "name" : "default",
            "definition" : {
              "mappings": { 
                "dynamic": false,
                "fields": { 
                  "products": { 
                    "type": "embeddedDocuments",
                    "dynamic": true,
                    "storedSource": true
                  } 
                }
              },
              "storedSource": {
                "include": [ "_id", "name" ]
              }
            }
	    } ]
	});

    // Convert your command to BSON
    if (!bson_init_from_json(&cmd, cmd_str, -1, &error)) {
        fprintf(stderr, "Failed to parse command: %s\n", error.message);
        ok = false;
        goto cleanup;
    }

    // Create the Atlas search index by running the command
    if (!mongoc_collection_command_simple (collection, &cmd, NULL, NULL, &error)) {
        fprintf(stderr, "Failed to run createSearchIndexes: %s\n", error.message);
        ok = false;
        goto cleanup;
    }
    printf ("Index created!\n");

cleanup:
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mongoc_database_destroy (database);
   bson_destroy (&cmd);
   mongoc_cleanup ();
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up and initialize the .NET/C# project.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` and initialize your project in that directory:

   ```shell
   # Create a new directory and initialize the project
   mkdir atlas-search-project && cd atlas-search-project
   dotnet new console

   # Add the MongoDB .NET/C# Driver to your project
   dotnet add package MongoDB.Driver
   ```

   For more detailed installation instructions, see the [MongoDB .NET/C# Driver documentation.](https://www.mongodb.com/docs/drivers/csharp/current/get-started/)

2. Define the index.

   Paste the following code into the `Program.cs` file.

   ```csharp
   using MongoDB.Bson;
   using MongoDB.Driver;

   // Replace the connection string with your MongoDB deployment's connection string
   var uri = "<connection-string>";

   var client = new MongoClient(uri);

   var db = client.GetDatabase("<database>");
   var collection = db.GetCollection<BsonDocument>("<collection>");

   // Create the MongoDB Search index definition for the embeddedDocuments field
   var index =  new CreateSearchIndexModel(
     "default", new BsonDocument
     {
       { "mappings", new BsonDocument
         {
           // "dynamic" can be a boolean or an object with "typeSet" name
           { "dynamic", <true|false> | new BsonDocument { { "typeSet", "<typeSet-name>" } } },
           { "fields", new BsonDocument
             {
               { "<field-name>", new BsonDocument
                 {
                   { "type", "embeddedDocuments" },
                   // "dynamic" can be a boolean or an object with "typeSet" name
                   { "dynamic", <true|false> | new BsonDocument { { "typeSet", "<typeSet-name>" } } },
                   { "fields", new BsonDocument
                     {
                       { "<field-name>", new BsonDocument
                         {
                           // <field-mapping-definition>
                         }
                       }
                       // ... additional fields 
                     }
                   }
                 }
               }
               // ... additional fields 
             }
           }
         }
       },
       { "typeSets", new BsonArray
         {
           new BsonDocument
           {
             { "name", "<typeSet-name>" },
             { "types", new BsonArray
               {
                 new BsonDocument
                 {
                   // <field-type-configuration>
                 }
                 // ... additional types 
               }
             }
           }
           // ... additional typeSets 
         }
       }
     });

   var result = collection.SearchIndexes.CreateOne(index);
   Console.WriteLine($"New index name: {result}");
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   dotnet run Program.cs
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```csharp
using MongoDB.Bson;
using MongoDB.Driver;

// Replace the connection string with your MongoDB deployment's connection string
var uri = "<connection-string>";

var client = new MongoClient(uri);

var db = client.GetDatabase("sample_supplies");
var collection = db.GetCollection<BsonDocument>("sales");

// Create the MongoDB Search index definition for the embeddedDocuments field
var index =  new CreateSearchIndexModel(
  "default", new BsonDocument
  {
    { "mappings", new BsonDocument
      {
        { "dynamic", false },
        { "fields", new BsonDocument
          {
            { "items", new BsonDocument
              {
                { "type", "embeddedDocuments" },
                { "dynamic", true }
              }
            }
          }
        }
      }
    }
  });

var result = collection.SearchIndexes.CreateOne(index);
Console.WriteLine($"New index name: {result}");
```

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```csharp
using MongoDB.Bson;
using MongoDB.Driver;

// Replace the connection string with your MongoDB deployment's connection string
var uri = "<connection-string>";

var client = new MongoClient(uri);

var db = client.GetDatabase("sample_training");
var collection = db.GetCollection<BsonDocument>("companies");

// Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
var index =  new CreateSearchIndexModel(
  "default", new BsonDocument
  {
    { "mappings", new BsonDocument
      {
        { "dynamic", true },
        { "fields", new BsonDocument
          {
            { "products", new BsonDocument
              {
                { "dynamic", true },
                { "type", "embeddedDocuments" }
              }
            },
            { "category_code", new BsonDocument
              {
                { "type", "token" }
              }
            }
          }
        }
      }
    }
  });

var result = collection.SearchIndexes.CreateOne(index);
Console.WriteLine($"New index name: {result}");
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```csharp
using MongoDB.Bson;
using MongoDB.Driver;

// Replace the connection string with your MongoDB deployment's connection string
var uri = "<connection-string>";

var client = new MongoClient(uri);

var db = client.GetDatabase("sample_training");
var collection = db.GetCollection<BsonDocument>("companies");

// Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
var index =  new CreateSearchIndexModel(
  "default", new BsonDocument
  {
    { "mappings", new BsonDocument
      {
        { "fields", new BsonDocument
          {
            { "offices", new BsonDocument
              {
                { "type", "embeddedDocuments" },
                { "dynamic", false },
                { "fields", new BsonDocument
                  {
                    { "country_code", new BsonDocument
                      {
                        { "type", "string" }
                      }
                    },
                    { "state_code", new BsonDocument
                      {
                        { "type", "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  });

var result = collection.SearchIndexes.CreateOne(index);
Console.WriteLine($"New index name: {result}");
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up the C++ project.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` for this project:

   ```shell
   # Create a new directory for the project
   mkdir atlas-search-project && cd atlas-search-project
   ```

   For more detailed installation instructions, see the [MongoDB C++ Driver documentation.](https://www.mongodb.com/docs/languages/cpp/cpp-driver/current/get-started/)

2. Define the index.

   Create a `CreateIndex.cpp` file in your project directory, and copy and paste the following code into the file.

   ```cpp
   #include <iostream>

   #include <bsoncxx/builder/basic/document.hpp>
   #include <bsoncxx/json.hpp>
   #include <mongocxx/client.hpp>
   #include <mongocxx/instance.hpp>
   #include <mongocxx/uri.hpp>

   using bsoncxx::builder::basic::kvp;
   using bsoncxx::builder::basic::make_document;

   int main() {
       // Initialize the MongoDB C++ driver
       mongocxx::instance instance{};

       // Connect to your MongoDB deployment
       mongocxx::uri uri("<connection-string>");
       mongocxx::client client(uri);

       auto db = client["<database>"];
       auto collection = db["<collection>"];
       auto siv = collection.search_indexes();

       // Create the MongoDB Search index definition for the embeddedDocuments field
       auto name = "default";
       auto definition = make_document(
           kvp("mappings", make_document(
               kvp("dynamic", true|false) | make_document(kvp("typeset", "<type-set-name>")),
               kvp("fields", make_document(
                   kvp("<field-name>", make_document(
                       kvp("type", "embeddedDocuments"),
                       kvp("dynamic", true|false) | make_document(kvp("typeset", "<type-set-name>")),
                       kvp("fields", make_document(
                           kvp("<field-name>", make_document(
                               // <field-mapping-definition>
                           )),
                           // ... additional fields
                       )),
                       kvp("storedSource", true|false) | make_document(kvp("include", bsoncxx::builder::basic::array{"<field-name>", ...})) | make_document(kvp("exclude", bsoncxx::builder::basic::array{"<field-name>", ...}))
                   )),
                   // ... additional fields
               ))
           )),
           kvp("typeSets", bsoncxx::builder::basic::array{
               make_document(
                   kvp("name", "<type-set-name>"),
                   kvp("types", bsoncxx::builder::basic::array{
                       make_document(
                           kvp("type", "<field-type>")
                           // ... additional field type configuration
                       )
                       // ... additional types
                   })
               )
               // ... additional typeSets
           })
       );
       auto model = mongocxx::search_index_model(name, definition.view());

       try {
           // Execute the command to create the index
           auto result = siv.create_one(model);
           std::cout << "New index name: " << result << std::endl;
       } catch (const std::exception& e) {
           std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
       }
   }
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   c++ --std=c++17 CreateIndex.cpp $(pkg-config --cflags --libs libmongocxx) -o ./app.out
   ./app.out
   ```

   **Output:**

   ```text
   New index name: default
   ```

   **Tip: MacOS Error**

   MacOS users might see the following error after running the preceding commands:

   ```sh
   dyld[54430]: Library not loaded: @rpath/libmongocxx._noabi.dylib
   ```

   To resolve this error, use the `-Wl`,\`\`-rpath\`\` linker option to set the `@rpath`, as shown in the following code:

   ```sh
   c++ --std=c++17 CreateIndex.cpp -Wl,-rpath,/usr/local/lib/ $(pkg-config --cflags --libs libmongocxx) -o ./app.out
   ./app.out
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the MongoDB Search index definition for the embeddedDocuments field
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("products", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", true)
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }
}
```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", true),
            kvp("fields", make_document(
                kvp("products", make_document(
                    kvp("dynamic", true),
                    kvp("type", "embeddedDocuments")
                )),
                kvp("category_code", make_document(
                    kvp("type", "token")
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }

}
```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the Atlas Search index definition for the embeddedDocuments field with dynamic mapping
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("relationships", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", make_document(
                        kvp("typeSet", "stringBooleanIndex")
                    )),
                    kvp("fields", make_document(
                        kvp("person", make_document(
                            kvp("type", "document"),
                            kvp("dynamic", make_document(
                                kvp("typeSet", "stringBooleanIndex")
                            ))
                        ))
                    ))
                ))
            ))
        )),
        kvp("typeSets", []{
            auto arr = bsoncxx::builder::basic::array{};
            arr.append(make_document(
                kvp("name", "stringBooleanIndex"),
                kvp("types", []{
                    auto types_arr = bsoncxx::builder::basic::array{};
                    types_arr.append(make_document(kvp("type", "boolean")));
                    types_arr.append(make_document(kvp("type", "string")));
                    return types_arr;
                }())
            ));
            return arr;
        }())
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }

}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("fields", make_document(
                kvp("offices", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", false),
                    kvp("fields", make_document(
                        kvp("country_code", make_document(
                            kvp("type", "string")
                        )),
                        kvp("state_code", make_document(
                            kvp("type", "string")
                        ))
                    ))
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }

}
```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the Atlas Search index definition for the embeddedDocuments field
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("funding_rounds", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", true),
                    kvp("storedSource", make_document(
                        kvp("include", bsoncxx::builder::basic::array{
                            "round_code", "raised_currency_code", "raised_amount"
                        })
                    ))
                ))
            ))
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }
}
```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```cpp
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;

int main() {
    // Initialize the MongoDB C++ driver
    mongocxx::instance instance{};

    // Connect to your MongoDB deployment
    mongocxx::uri uri("<connection-string>");
    mongocxx::client client(uri);

    auto db = client["sample_training"];
    auto collection = db["companies"];
    auto siv = collection.search_indexes();

    // Create the Atlas Search index definition for the embeddedDocuments field
    auto name = "default";
    auto definition = make_document(
        kvp("mappings", make_document(
            kvp("dynamic", false),
            kvp("fields", make_document(
                kvp("products", make_document(
                    kvp("type", "embeddedDocuments"),
                    kvp("dynamic", true),
                    kvp("storedSource", true)
                ))
            ))
        )),
        kvp("storedSource", make_document(
            kvp("include", bsoncxx::builder::basic::array{ "_id", "name" })
        ))
    );
    auto model = mongocxx::search_index_model(name, definition.view());

    try {
        // Execute the command to create the index
        auto result = siv.create_one(model);
        std::cout << "New index name: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error creating Atlas Search index: " << e.what() << std::endl;
    }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up and initialize the Go module.

   In your terminal, navigate to where you want to create your application, then run the following command to create a directory called `atlas-search-project` and initialize your project in that directory:

   ```shell
   # Create a new directory and initialize the project
   mkdir atlas-search-project && cd atlas-search-project
   go mod init atlas-search-project

   # Add the MongoDB Go Driver to your project
   go get go.mongodb.org/mongo-driver/v2/mongo
   ```

   For more detailed installation instructions, see the [MongoDB Go Driver documentation.](https://www.mongodb.com/docs/drivers/go/current/get-started.md#std-label-go-get-started)

2. Define the index.

   Create a `create_index.go` file in your project directory, and copy and paste the following code into the file.

   ```go
   package main

   import (
   	"context"
   	"fmt"
   	"log"

   	"go.mongodb.org/mongo-driver/v2/bson"
   	"go.mongodb.org/mongo-driver/v2/mongo"
   	"go.mongodb.org/mongo-driver/v2/mongo/options"
   )

   func main() {
   	ctx := context.Background()
   	uri := "<connection-string>"
   	client, err := mongo.Connect(options.Client().
   		ApplyURI(uri))
   	if err != nil {
   		panic(err)
   	}

   	defer func() {
   		if err := client.Disconnect(context.TODO()); err != nil {
   			panic(err)
   		}
   	}()

   	coll := client.Database("<database>").Collection("<collection>")
   	const indexName = "defaultgo"
   	opts := options.SearchIndexes().SetName(indexName).SetType("search")

   	// Define the MongoDB Search index for the embeddedDocuments field
   	searchIndexModel := mongo.SearchIndexModel{
   		Definition: bson.D{
   			{"mappings", bson.D{
   				// "dynamic" can be a boolean or an object with "typeset" name
   				{"dynamic", true}, // or false, or bson.D{{"typeset", "<type-set-name>"}}
   				{"fields", bson.D{
   					{"<field-name>", bson.D{
   						{"type", "embeddedDocuments"},
   						// "dynamic" can be a boolean or an object with "typeSet" name
   						{"dynamic", true}, // or false, or bson.D{{"typeSet", "<type-set-name>"}}
   						{"fields", bson.D{
   							{"<field-name>", bson.D{
   								// <field-mapping-definition>
   							}},
   							// ... additional fields
   						}},
   						{"storedSource", true}, // or false, or bson.D{{"include", bson.A{"<field-name>", /* ... */}}} or bson.D{{"exclude", bson.A{"<field-name>", /* ... */}}}
   					}},
   					// ... additional fields
   				}},
   			}},
   			{"typeSets", bson.A{
   				bson.D{
   					{"name", "<type-set-name>"},
   					{"types", bson.A{
   						bson.D{
   							{"type", "<field-type>"},
   							// ... additional field type configuration
   						},
   						// ... additional types
   					}},
   				},
   				// ... additional typeSets
   			}},
   		},
   		Options: opts,
   	}

   	// Create the index
   	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
   	if err != nil {
   		log.Fatalf("Failed to create the Atlas Search index: %v", err)
   	}

   	fmt.Println("Name of index created: " + searchIndexName)
   }

   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   ### Atlas Cluster

   Your connection string should use the following format:

   ```text
   mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net
   ```

   IMPORTANT: Ensure that your connection string includes your database user's credentials. To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

3. Create the index.

   ```shell
   go run create_index.go
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the MongoDB Search index for the embeddedDocuments field
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"products", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", true},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the MongoDB Search index for the embeddedDocuments field with dynamic mapping
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", true},
				{"fields", bson.D{
					{"products", bson.D{
						{"dynamic", true},
						{"type", "embeddedDocuments"},
					}},
					{"category_code", bson.D{
						{"type", "token"},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the Atlas Search index for the embeddedDocuments field with dynamic mapping
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"relationships", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", bson.D{
							{"typeSet", "stringBooleanIndex"},
						}},
						{"fields", bson.D{
							{"person", bson.D{
								{"type", "document"},
								{"dynamic", bson.D{
									{"typeSet", "stringBooleanIndex"},
								}},
							}},
						}},
					}},
				}},
			}},
			{"typeSets", bson.A{
				bson.D{
					{"name", "stringBooleanIndex"},
					{"types", bson.A{
						bson.D{{"type", "boolean"}},
						bson.D{{"type", "string"}},
					}},
				},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the MongoDB Search index for the embeddedDocuments field with specified fields
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"fields", bson.D{
					{"offices", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", false},
						{"fields", bson.D{
							{"country_code", bson.D{
								{"type", "string"},
							}},
							{"state_code", bson.D{
								{"type", "string"},
							}},
						}},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the Atlas Search index for the embeddedDocuments field
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"funding_rounds", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", true},
						{"storedSource", bson.D{
							{"include", bson.A{"round_code", "raised_currency_code", "raised_amount"}},
						}},
					}},
				}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```go
package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
	ctx := context.Background()
	uri := "<connection-string>"
	client, err := mongo.Connect(options.Client().
		ApplyURI(uri))
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			panic(err)
		}
	}()

	coll := client.Database("sample_training").Collection("companies")
	const indexName = "default"
	opts := options.SearchIndexes().SetName(indexName).SetType("search")

	// Define the Atlas Search index for the embeddedDocuments field
	searchIndexModel := mongo.SearchIndexModel{
		Definition: bson.D{
			{"mappings", bson.D{
				{"dynamic", false},
				{"fields", bson.D{
					{"products", bson.D{
						{"type", "embeddedDocuments"},
						{"dynamic", true},
						{"storedSource", true},
					}},
				}},
			}},
			{"storedSource", bson.D{
				{"include", bson.A{"_id", "name"}},
			}},
		},
		Options: opts,
	}

	// Create the index
	searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
	if err != nil {
		log.Fatalf("Failed to create the Atlas Search index: %v", err)
	}

	fmt.Println("Name of index created: " + searchIndexName)
}

```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up your Java project with the MongoDB Java driver.

   In your IDE, create a new [Maven](https://maven.apache.org/) or [Gradle](https://gradle.org/) project. Add the Bill of Materials (BOM) for MongoDB JVM artifacts to your project to organize dependency versions. The BOM simplifies dependency management by ensuring that you maintain consistent and compatible versions of dependencies, such as between the Java driver and the core driver library. Use the BOM to avoid version conflicts and simplify upgrades.

   Select from the following **Maven** and **Gradle** tabs to view instructions for adding the BOM for each dependency manager:

   ### Maven

   Add the following code to the `dependencyManagement` list in your `pom.xml` file:

   ```xml
   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.mongodb</groupId>
               <artifactId>mongodb-driver-bom</artifactId>
               <version>5.5.1</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>
   ```

   To view a list of dependencies that the BOM manages, see the [mongodb-driver-bom dependency listing](https://mvnrepository.com/artifact/org.mongodb/mongodb-driver-bom/5.51) on the Maven Repository website.

   After adding the BOM, select from the following **Maven** and **Gradle** tabs to view instructions for adding the MongoDB Java Sync Driver as a dependency in your project:

   ### Maven

   Add the following code to the `dependencies` array in your Maven project's `pom.xml` file:

   ```xml
   <dependencies>
       <dependency>    
         <groupId>org.mongodb</groupId>    
         <artifactId>mongodb-driver-sync</artifactId>    
         <version>4.11.1</version>    
       </dependency>
   </dependencies>

   ```

   Run your package manager to install the dependencies to your project.

   For more detailed installation instructions and version compatibility, see the [MongoDB Java Driver documentation.](https://www.mongodb.com/docs/drivers/java/sync/current/get-started/)

2. Define the index.

   In your project's base package directory, create a `CreateIndex.java` file and copy and paste the following code into this file.

   ```java
   import com.mongodb.client.*;
   import org.bson.Document;

   public class CreateIndex {
       public static void main(String[] args) {
           // Replace the connection string with your MongoDB deployment's connection string
           String connectionString = "<connection-string>";

           try (MongoClient mongoClient = MongoClients.create(connectionString)) {
               MongoDatabase database = mongoClient.getDatabase("<database>");
               MongoCollection<Document> collection = database.getCollection("<collection>");
               String indexName = "default";

               // Create the MongoDB Search index definition for the embeddedDocuments field
               Document searchIdx = new Document("mappings",
                   new Document("dynamic", true) // or false, or new Document("typeset", "<type-set-name>")
                       .append("fields", new Document(
                           "<field-name>", new Document()
                               .append("type", "embeddedDocuments")
                               .append("dynamic", true) // or false, or new Document("typeSet", "<type-set-name>")
                               .append("fields", new Document(
                                   "<field-name>", new Document()
                                       // <field-mapping-definition>
                               ))
                               .append("storedSource", true) // or false, or new Document("include", java.util.Arrays.asList("<field-name>", ...)) or new Document("exclude", java.util.Arrays.asList("<field-name>", ...))
                           )
                           // ... additional fields
                       ))
               ).append("typeSets",
                   java.util.Arrays.asList(
                       new Document("name", "<type-set-name>")
                           .append("types", java.util.Arrays.asList(
                               new Document("type", "<field-type>")
                                   // ... additional field type configuration
                               // ... additional types
                           ))
                       // ... additional typeSets
                   )
               );
               collection.createSearchIndex(indexName, searchIdx);
               System.out.println("New index name: " + indexName);
           } catch (Exception e) {
               System.err.println("Error creating Atlas Search index: " + e.getMessage());
           }
       }
   }
   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Compile and run the file to create the index.

   Compile and run your application in your IDE or your shell.

   ```shell
   javac CreateIndex.java
   java CreateIndex
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```java
import com.mongodb.client.*;
import org.bson.Document;

public class CreateIndex {
    public static void main(String[] args) {
        // Replace the connection string with your MongoDB deployment's connection string
        String connectionString = "<connection-string>";

        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
            MongoDatabase database = mongoClient.getDatabase("sample_training");
            MongoCollection<Document> collection = database.getCollection("companies");
            String indexName = "default";

            // Create the MongoDB Search index definition for the embeddedDocuments field
            Document searchIdx = new Document(
                    "mappings",
                    new Document("dynamic", false)
                            .append("fields",
                                    new Document("products",
                                            new Document("type", "embeddedDocuments")
                                                .append("dynamic", true)))
            );
            collection.createSearchIndex(indexName, searchIdx);
            System.out.println("New index name: " + indexName);
        } catch (Exception e) {
            System.err.println("Error creating Atlas Search index: " + e.getMessage());
        }
    }
}
```

### Dynamic Index Example

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```java
import com.mongodb.client.*;
import org.bson.Document;

public class CreateIndex {
    public static void main(String[] args) {
        // Replace the connection string with your MongoDB deployment's connection string
        String connectionString = "<connection-string>";

        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
            MongoDatabase database = mongoClient.getDatabase("sample_training");
            MongoCollection<Document> collection = database.getCollection("companies");
            String indexName = "default";

            // Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
            Document searchIdx = new Document(
                    "mappings",
                    new Document("dynamic", true)
                            .append("fields",
                                    new Document("products",
                                            new Document("dynamic", true)
                                                    .append("type", "embeddedDocuments"))
                                            .append("category_code",
                                                    new Document("type", "token")))
            );
            collection.createSearchIndex(indexName, searchIdx);
            System.out.println("New index name: " + indexName);
        } catch (Exception e) {
            System.err.println("Error creating Atlas Search index: " + e.getMessage());
        }
    }
}
```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```java
import com.mongodb.client.*;
import org.bson.Document;

public class CreateIndex {
    public static void main(String[] args) {
        // Replace the connection string with your MongoDB deployment's connection string
        String connectionString = "<connection-string>";

        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
            MongoDatabase database = mongoClient.getDatabase("sample_training");
            MongoCollection<Document> collection = database.getCollection("companies");
            String indexName = "default";

            // Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
            Document searchIdx = new Document(
                    "mappings",
                    new Document("fields",
                            new Document("offices",
                                    new Document("type", "embeddedDocuments")
                                            .append("dynamic", false)
                                            .append("fields",
                                                    new Document("country_code", new Document("type", "string"))
                                                            .append("state_code", new Document("type", "string")))))
            );
            collection.createSearchIndex(indexName, searchIdx);
            System.out.println("New index name: " + indexName);
        } catch (Exception e) {
            System.err.println("Error creating Atlas Search index: " + e.getMessage());
        }
    }
}
```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Initialize your Node.js project.

   ```shell
   # Create a new directory and initialize the project
   mkdir atlas-search-project && cd atlas-search-project
   npm init -y

   # Add the MongoDB Node.js Driver to your project
   npm install mongodb
   ```

   For detailed installation instructions, see the [MongoDB Node Driver documentation.](https://www.mongodb.com/docs/drivers/node/current/)

2. Define the index.

   Create a `create-index.js` file in your project directory, and copy and paste the following code into the file.

   ```javascript
   const { MongoClient } = require("mongodb");

   // Replace the connection string with your MongoDB deployment's connection string
   const uri =  "<connection-string>";

   const client = new MongoClient(uri);

   async function run() {
     try {
       const database = client.db("<database>");
       const collection = database.collection("<collection>");

       // Create the MongoDB Search index definition for the embeddedDocuments field
       const index = {
           name: "default",
           definition: {
             "mappings": {
               "dynamic": true, // or false, or { "typeset": "<type-set-name>" }
               "fields": {
                 "<field-name>": {
                   "type": "embeddedDocuments",
                   "dynamic": true, // or false, or { "typeSet": "<type-set-name>" }
                   "fields": {
                     "<field-name>": {
                       // <field-mapping-definition>
                     }
                   },
                   "storedSource": true // or false, or { "include": ["<field-name>", ...] } or { "exclude": ["<field-name>", ...] }
                 }
                 // ... additional fields
               }
             },
             "typeSets": [
               {
                 "name": "<type-set-name>",
                 "types": [
                   {
                     "type": "<field-type>"
                     // ... additional field type configuration
                   }
                   // ... additional types
                 ]
               }
               // ... additional typeSets
             ]
           }
       }

       // Create the index
       const result = await collection.createSearchIndex(index);
       console.log("New index name: " + result);
     } finally {
       await client.close();
     }
   }

   run().catch(console.dir);

   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   node create-index.js
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the MongoDB Search index definition for the embeddedDocuments field
    const index = {
        name: "default",
        definition: {
            "mappings": {
                "dynamic": false,
                "fields": {
                    "products": {
                        "type": "embeddedDocuments",
                        "dynamic": true
                    }
                }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
    const index = {
        name: "default",
        definition: {
            "mappings": {
                "dynamic": true,
                "fields": {
                    "products": {
                        "dynamic": true,
                        "type": "embeddedDocuments"
                    },
                    "category_code": {
                        "type": "token"
                    }
                }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the Atlas Search index definition for the embeddedDocuments field with dynamic mapping
    const index = {
        name: "default",
        definition: {
          "mappings": {
            "dynamic": false,
            "fields": {
              "relationships": {
                "type": "embeddedDocuments",
                "dynamic": {
                  "typeSet": "stringBooleanIndex"
                },
                "fields": {
                  "person": {
                    "type": "document",
                    "dynamic": {
                      "typeSet": "stringBooleanIndex"
                    }
                  }
                }
              }
            }
          },
          "typeSets": [
            {
              "name": "stringBooleanIndex",
              "types": [
                {
                  "type": "boolean"
                },
                {
                  "type": "string"
                }
              ]
            }
          ]
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
    const index = {
        name: "default",
        definition: {
            "mappings": {
                "fields": {
                    "offices": {
                        "type": "embeddedDocuments",
                        "dynamic": false,
                        "fields": {
                            "country_code": {
                                "type": "string"
                            },
                            "state_code": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the Atlas Search index definition for the embeddedDocuments field
    const index = {
        name: "default",
        definition: {
            "mappings": { 
              "dynamic": false,
              "fields": { 
                "funding_rounds": { 
                  "type": "embeddedDocuments",
                  "dynamic": true,
                  "storedSource": {
                    "include": ["round_code", "raised_currency_code", "raised_amount"] 
                  }
                } 
              }
            }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```javascript
const { MongoClient } = require("mongodb");

// Replace the connection string with your MongoDB deployment's connection string
const uri =  "<connection-string>";

const client = new MongoClient(uri);

async function run() {
  try {
    const database = client.db("sample_training");
    const collection = database.collection("companies");

    // Create the Atlas Search index definition for the embeddedDocuments field
    const index = {
        name: "default",
        definition: {
          "mappings": { 
            "dynamic": false,
            "fields": { 
              "products": { 
                "type": "embeddedDocuments",
                "dynamic": true,
                "storedSource": true
              } 
            }
          },
          "storedSource": {
            "include": [ "_id", "name" ]
          }
        }
    }

    // Create the index
    const result = await collection.createSearchIndex(index);
    console.log("New index name: " + result);
  } finally {
    await client.close();
  }
}

run().catch(console.dir);

```

You can use the MongoDB Search `embeddedDocuments` type to index fields in documents and objects that are elements of an array. MongoDB Search indexes embedded documents independent of their parent document. Each indexed document contains only fields that are part of the embedded document array element.

To query fields indexed within an `embeddedDocuments` mapping, you must do one of the following:

- Use the [embeddedDocument](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref) operator with the `path` specified as the `embeddedDocuments` field.

- Use `storedSource` index option and specify the `embeddedDocuments` field in the `returnScope` query option.

You can also [configure dynamic mappings](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) to automatically index fields that are part of the embedded document array element.

## Considerations

### Facet on Embedded Documents

You can facet on date, numeric, and string fields within `embeddedDocuments` type field to retrieve facet counts based on the number of matching `embeddedDocuments` elements. To do this, you must:

1. Configure `storedSource` to store `embeddedDocuments` type fields.

2. Set the query option `returnScope.path` as the `embeddedDocuments` field. To learn more about the syntax and usage of `returnScope`, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

To facet on fields within objects in arrays based on the number of matching root documents, index the path as a `document` type.

### Stored Source for Embedded Documents

You can use the [storedSource](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) option to store and return fields inside an `embeddedDocuments` type. You can configure all or a subset of the fields to store or exclude from storage at each level of nesting. This allows you to return only the objects within the array that match the query criteria, rather than the entire root document. To learn more about the syntax for `storedSource`, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition)

To return the stored field:

- Specify `returnScope.path` option as the `embeddedDocuments` type field. To learn more, see [Query, Filter, and Retrieve Arrays of Objects.](https://www.mongodb.com/docs/search/query/return-scope.md#std-label-fts-return-scope)

- Set `returnStoredSource` to `true` to retrieve only the stored fields instead of entire documents from the collection. To learn more, see [Return Stored Source Fields.](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option)

You can't include `embeddedDocuments` fields that were specified as `storedSource.exclude` at a higher-level.

### `embeddedDocuments` Type Limitations

The following limitations apply when indexing with the `embeddedDocument` type:

- You can use `embeddedDocuments` only on fields with up to `5` levels of nesting. An `embeddedDocuments` field can't have more than `4` parent `embeddedDocuments` fields.

- You can't define a field inside the `embeddedDocuments` type as the deprecated [knnVector](https://www.mongodb.com/docs/search/indexes/field-types/knn-vector.md#std-label-fts-data-types-knn-vector) type.

- For [highlighting](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents, you must also index the parent of the field that you want to highlight as the [document](https://www.mongodb.com/docs/search/indexes/field-types/document-type.md#std-label-bson-data-types-document) type.

- The following operations require you to also 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:

  - [Facet](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) on fields within objects in arrays based on the number of matching root documents.

  - [Highlight](https://www.mongodb.com/docs/search/query/highlighting.md#std-label-highlight-ref) fields within embedded documents. For an example, see the [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) tutorial.

  - [Sort](https://www.mongodb.com/docs/search/query/sort.md#std-label-sort-ref) the parent documents by a nested field. You must also index the fields that you want to use for sorting.

#### 2,100,000,000 Index Objects Limit

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)

The exact number of index objects can vary based on the rate of document changes and deletions. The [Search Max Number of Lucene Docs](https://www.mongodb.com/docs/atlas/review-atlas-search-metrics.md#std-label-review-atlas-search-metrics) metric shows the largest number of Lucene documents in a single partition of any search index within a replica set or shard.

For example, suppose the metric displays "1,500,000,000." The index with the highest number of Lucene documents in a single partition has about 1,500,000,000 documents in that partition. If the index uses many partitions, it can contain more documents overall.

You can approximate the expected number of index objects in a single index by doing the following steps:

1. Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.

   ```shell
   number of index objects in document = 1 + number of nested embedded documents
   ```

2. Multiply the number of index objects per document by the total number of documents in the collection

   ```shell
   total number of index objects = number of index objects in document x total number of documents in collection
   ```

Note that this approximation is a lower bound.

**Example:**

Consider the [collection](https://search-playground.mongodb.com/tools/code-sandbox/snapshots/6601831bf3ec7476bd9da8c9) named `schools`, described in this [tutorial](https://www.mongodb.com/docs/search/tutorial/embedded-documents-tutorial.md#std-label-embedded-documents-tutorial-sample-collection), and suppose the collection contains 1000 documents similar to the following:

```json
{
  "_id": 0,
  "name": "Springfield High",
  "mascot": "Pumas",
  "teachers": [
    {
      "first": "Jane",
      "last": "Smith",
      "classes": [
        {
          "subject": "art of science",
          "grade": "12th"
        },
        ... // 2 more embedded documents
      ]
    },
    ... // 1 more embedded document
  ],
  "clubs": {
    "stem": [
      {
        "club_name": "chess",
        "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
      },
      ... // 1 more embedded document
    ],
    ... // 1 more embedded document
  }
}
```

Now consider the index definition for the following fields in the `schools` collection:

### Nested Array

The array of documents named `teachers` is indexed as the `embeddedDocuments` type with dynamic mappings enabled. However, the `classes` field *isn't indexed*. Use the following to calculate the index objects:

1. Calculate the number of index objects per document.

   ```shell
   Number of ``teachers`` embedded documents = up to 2
   Total number of index objects per document = 1 + 2 = 3
   ```

2. Multiply by the total number of documents in the collection.

   ```shell
   Number of documents in the collection = 1000
   Number of index objects per document = 3
   Total number of index objects for collection = 1000 x 3 = 3000
   ```

If your collection has large arrays that might generate 2,100,000,000 index objects, you must [shard](https://www.mongodb.com/docs/atlas/cluster-additional-settings.md#std-label-create-cluster-sharding) any clusters that contain indexes with the `embeddedDocuments` type.

## Define the Index for the `embeddedDocuments` Type

1. Set up the Python project.

   ```shell
   # Create a new directory for the project
   mkdir atlas-search-project && cd atlas-search-project

   # Install PyMongo
   pip install pymongo
   ```

   For detailed installation instructions, see [MongoDB Python Driver (PyMongo).](https://www.mongodb.com/docs/languages/python/pymongo-driver/get-started.md#std-label-pymongo-get-started-download-and-install)

2. Define the index.

   Create a `create_index.py` file in your project directory, and copy and paste the following code into the file.

   ```python
   from pymongo import MongoClient
   from pymongo.operations import SearchIndexModel

   # Connect to your Atlas deployment
   uri = "<connection-string>"
   client = MongoClient(uri)

   database = client["<database>"]
   collection = database["<collection>"]

   # Create the MongoDB Search index definition for the embeddedDocuments field
   search_index_model = SearchIndexModel(
       definition={
           "mappings": {
             "dynamic": <True|False> | {
               "typeSet": "<typeSet-name>"
             },
             "fields": {
               "<field-name>": {
                 "type": "embeddedDocuments",
                 "dynamic": <True|False> | {
                   "typeSet": "<typeSet-name>"
                 },
                 "fields": {
                   "<field-name>": {
                     <field-mapping-definition>
                   }
                 },
                 "storedSource": <True|False>  | {"include" | "exclude": ["<field-name>", ...]}
               },
               ...
             }
           },
           "typeSets": [
             {
               "name": "<typeSet-name>",
               "types": [
                 {
                   "type": "<field-type>",
                   ... 
                 },
                 ...
               ]
             },
             ...
           ]
       },
       name="default",
   )

   # Create the index
   result = collection.create_search_index(model=search_index_model)
   print(f"New index name: {result}")

   ```

   Replace `<connection-string>` with the connection string for your Atlas cluster or local Atlas deployment.

   To learn more about finding your connection string, see [Connect to a Cluster via Client Libraries.](https://www.mongodb.com/docs/atlas/driver-connection.md#std-label-connect-via-driver)

   **Note:**

   For a local or self-managed deployment, your connection string should use the following format:

   ```text
   mongodb://localhost:<port-number>/?directConnection=true
   ```

   To learn more, see [Connection Strings.](https://www.mongodb.com/docs/manual/reference/connection-string.md#std-label-mongodb-uri)

3. Create the index.

   ```shell
   python create_index.py
   ```

   **Output:**

   ```text
   New index name: default
   ```

## Configure `embeddedDocuments` Field Properties

The MongoDB Search `embeddedDocuments` type takes the following parameters:

| Field | Type | Necessity | Description | Default |
| --- | --- | --- | --- | --- |
| `type` | String | Required | Human-readable label that identifies the field type. Value must be `embeddedDocuments`. | |
| `dynamic` | Boolean or Object | Optional | Flag that specifies whether to dynamically index using default type set or object that references the name of the configured `typeSet` that contains the list of field types to dynamically index. Value must be one of the following: boolean - set to `true` to recursively index all indexable field types or set to `false` to not dynamically index any of the dynamically indexable field types. For the list of field types that MongoDB Search dynamically indexes using the default type set, see [Enable Default `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-enable-dynamic-mappings); object - specify the name `typeSets` that contains the list of field types to index. To learn more, see `dynamic.typeSet`. If you set this to `false`, you must specify individual fields to index using `fields` object. You can also configure individual fields to index separately using the `fields` object. | `false` |
| `dynamic.typeSet` | String | Optional | Name of the `typeSet` array of objects that configures the field types to index. To learn more, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `fields` | Object | Optional | Fields to index. This is required if `dynamic` is `false`. If `dynamic` is `true`, MongoDB Search indexes all indexable field types. You can also independently index individual fields using `fields`. MongoDB Search doesn't support indexing facet fields as part of an `embeddedDocuments` field. | `{}` |
| `storedSource` | Boolean or [Stored Source Definition](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | Optional | Specifies fields in the documents to store for query-time look-ups using the [returnedStoredSource](https://www.mongodb.com/docs/search/query/return-stored-source.md#std-label-fts-return-stored-source-option) option. You can store fields of all [MongoDB Search Field Types](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-bson-data-chart) on MongoDB Search. Value can be one of the following: `true`, to store all fields; `false`, to not store any fields; [Object](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-document) that specifies the fields to `include` or `exclude` from storage If omitted, defaults to `false`. To learn more, see [Define Stored Source Fields in Your MongoDB Search Index.](https://www.mongodb.com/docs/search/indexes/stored-source-definition.md#std-label-fts-stored-source-definition) | `false` |
| `typeSets` | Array of Objects | Optional | Field types to index automatically using dynamic mappings. To learn about the field types that you can configure for dynamic mappings, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |
| `typeSets.[n].name` | String | Required | Human-readable label that identifies the configuration for the fields types to dynamically index. | |
| `typeSets.[n].types` | Array of Objects | Required | Field types, one per object, to index automatically using dynamic mappings. | |
| `typeSets.[n].types.[n].type` | String | Required | Field type to automatically index. You can also configure the settings for each field type. If you don't configure any settings, MongoDB Search uses the default values for the field type. To learn more about the field types that you can configure for dynamic mapping, see [Configure a `typeSet`.](https://www.mongodb.com/docs/search/indexes/define-field-mappings.md#std-label-fts-configure-dynamic-mappings) | |

## Try an Example for the `embeddedDocuments` Type

The following index definition examples use collections in the [sample data](https://www.mongodb.com/docs/manual/sample-data.md#std-label-available-sample-datasets). After you [load the sample data](https://www.mongodb.com/docs/atlas/import/load-sample-data.md#std-label-load-sample-data), you can use these examples to index fields as the `embeddedDocuments` type.

To learn how to set up and run the following example code, see [Define the Index for the token Type](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-define-index-token-admin-api).

### Basic Example

#### Automatically index all dynamically indexable fields inside the array of objects.

The following index definition for the `sample_training.companies` namespace indexes the array of objects in the `products` field. It also configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the MongoDB Search index definition for the embeddedDocuments field
search_index_model = SearchIndexModel(
    definition={
        "mappings": {
            "dynamic": False,
            "fields": {
                "products":{
                   "type": "embeddedDocuments",
                   "dynamic": True
                }
            }
        },
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

### Dynamic Index Examples

#### Combine dynamic mappings with static mappings to index nested fields as different field types.

#### Enable Dynamic Indexing

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to automatically index all dynamically indexable fields inside the objects in the `products` array. It also configures the `category_code` field to be indexed as the [token](https://www.mongodb.com/docs/search/indexes/field-types/token-type.md#std-label-bson-data-types-token) type, which is not included in the default type set for dynamic mappings, to support MongoDB Search [`facet` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/facet.md#std-label-fts-facet-ref) queries against that field.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the MongoDB Search index definition for the embeddedDocuments field with dynamic mapping
search_index_model = SearchIndexModel(
    definition={
        "mappings": {
            "dynamic": True,
            "fields": {
                "products": {
                    "dynamic": True,
                    "type": "embeddedDocuments"
                },
                "category_code": {
                    "type": "token"
                }
            }
        },
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

#### Configure Dynamic Indexing

The following index example disables dynamic mappings at the root level and uses static mappings to index the `relationships` field as the `embeddedDocuments` type. It also applies the configured `stringBooleanIndex` `typeSet` to index only the `string` and `boolean` types the `relationships` array of objects. It applies the `stringBooleanIndex` `typeSet` to the nested `person` document to index only the `boolean` and `string` types in the `person` document.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the Atlas Search index definition for the embeddedDocuments field with dynamic mapping
search_index_model = SearchIndexModel(
    definition={
      "mappings": {
        "dynamic": false,
        "fields": {
          "relationships": {
            "type": "embeddedDocuments",
            "dynamic": {
              "typeSet": "stringBooleanIndex"
            },
            "fields": {
              "person": {
                "type": "document",
                "dynamic": {
                  "typeSet": "stringBooleanIndex"
                }
              }
            }
          }
        }
      },
      "typeSets": [
        {
          "name": "stringBooleanIndex",
          "types": [
            {
              "type": "boolean"
            },
            {
              "type": "string"
            }
          ]
        }
      ]
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

### Specified Fields Example

#### Index only specific fields in the array of objects.

The following index definition for the `sample_training.companies` namespace configures MongoDB Search to index only the `country_code` and `state_code` fields as the MongoDB Search `string` type in the `offices` array of objects.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the MongoDB Search index definition for the embeddedDocuments field with specified fields
search_index_model = SearchIndexModel(
    definition={
        "mappings": {
            "fields": {
                "offices": {
                    "type": "embeddedDocuments",
                    "dynamic": False,
                    "fields": {
                        "country_code": {
                            "type": "string"
                        },
                        "state_code": {
                            "type": "string"
                        }
                    }
                }
            }
        },
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

### Stored Source Examples

#### Use storedSource to configure storage for nested fields in the array of objects for query and retrieval.

#### Use Relative Path for Stored Source

The following index definition automatically indexes all the fields in the `funding_rounds` array of objects for querying. It also uses the `storedSource` field to store the `round_code`, `raised_currency_code`, and `raised_amount` fields on `mongot`. This allows you to query these stored fields using any operator that supports queries against these field types and retrieve these stored fields inside the parent object (`funding_rounds`) as individual documents. For a sample query that demonstrates this, see the [`range` (MongoDB Search Operator)](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-ref) [Embedded Documents Example](https://www.mongodb.com/docs/search/query/operators-collectors/range.md#std-label-range-embedded-documents-eg). To query and retrieve other fields in the parent object (`funding_rounds`), you must use the `embeddedDocument` operator.

```python
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the Atlas Search index definition for the embeddedDocuments field
search_index_model = SearchIndexModel(
    definition={
        "mappings": { 
          "dynamic": false,
            "fields": { 
            "funding_rounds": { 
              "type": "embeddedDocuments",
              "dynamic": true,
              "storedSource": {
                "include": ["round_code", "raised_currency_code", "raised_amount"] 
              }
            } 
          }
        }
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

#### Configure Multiple Stored Source

The following index definition indexes all fields in the the `products` array of objects. It stores the `name` field independently for querying the `name` field and the `products` array of objects. You can use any operator that supports queries against the field types in the `products` array of objects to query and retrieve the stored fields as individual documents.

```text
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel

# Connect to your Atlas deployment
uri = "<connection-string>"
client = MongoClient(uri)

database = client["sample_training"]
collection = database["companies"]

# Create the Atlas Search index definition for the embeddedDocuments field
search_index_model = SearchIndexModel(
    definition={
        "mappings": { 
          "dynamic": false,
          "fields": { 
            "products": { 
              "type": "embeddedDocuments",
              "dynamic": true,
              "storedSource": true
            } 
          }
        },
        "storedSource": {
          "include": [ "_id", "name" ]
        }
    },
    name="default",
)

# Create the index
result = collection.create_search_index(model=search_index_model)
print(f"New index name: {result}")

```

## Learn More

To learn more about the `embeddedDocument` operator and see example queries, see [embeddedDocument.](https://www.mongodb.com/docs/search/query/operators-collectors/embedded-document.md#std-label-embedded-document-ref)

To learn how to query an embedded document, see the [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) tutorial.
