Optimize your MongoDB Search index performance by following resource allocation and scaling recommendations. Use the sections below to understand resource requirements, manage index build times, and plan cluster scaling for your deployment type.
Resource Requirements
Index Size and Configuration
Important
If you create a MongoDB Search index for a collection that has or will soon have more than 2.1 billion index objects, use the numPartitions index option to partition your index or shard your cluster. Index partitions are limited to 2.1 billion objects per partition.
Some index configuration options can lead to indexes that take up a significant proportion of your disk space. In some cases, your index could be many times larger than the size of your data. Although this is expected behavior, it's important to be aware of the following indexing-intensive features.
Note
Some limitations apply to MongoDB Search on Free clusters and Flex clusters only. To learn more, see MongoDB Search Search Free and Flex Tier Limitations.
Dynamic vs. Static Mappings
When you create an MongoDB Search index, field mapping defaults to dynamic, which means that MongoDB Search dynamically indexes all the datatypes that can be dynamically indexed in your collection. This can lead to large indexes if you have a large number of fields in your documents, or if you have fields with long string values.
To reduce the size and performance footprint of your index, we recommend using static mappings to specify the fields that you want to index and their types.
store Option
When indexing a text field as the MongoDB Search string type, you can set the store option to false to reduce the size of your index. This prevents MongoDB Search from storing the exact document text as well as the analyzed values in the index. However, setting store to false prevents you from using the highlight option to adds fields to the result set that display search terms in their original context.
Autocomplete
The MongoDB Search autocomplete field type creates indexes that you can use with the autocomplete operator to implement search-as-you-type functionality in your application. However, the autocomplete field type can create large indexes and take longer to build than other field types.
Use the following recommendations to reduce the size and performance footprint of the autocomplete type:
Use the
autocompletetype only for specific fields in static mappings. Using a customtypeSetdefinition to dynamically index string fields as theautocompletetype can apply theautocompletetype too broadly and significantly increase index size and resource usage. In addition, theautocompletetype has specialized, typeahead-oriented scoring behavior suited to specific field indexing, not broad dynamic application. To learn more aboutsimilarity.typescoring with theautocompletetype, see text, phrase, queryString, and autocomplete Operators.Avoid using
nGramas thetokenizationstrategy for theautocompletetype definition, as it creates more tokens for a given string thanedgeGramorrightEdgeGramtokenization.Set a smaller range between the
minGramsandmaxGramsoption values in theautocompletetype definition, which reduces the number of tokens created for each string.Generally, we recommend setting
maxGramsto the character count of the longest word in the field that you want to query. If you are unsure, for English language fields, we recommend starting withmaxGramsvalue of10.Setting a larger value for
minGramscan significantly reduce index size for fields in a collection with many documents. For example, settingminGramsto2instead of1creates 100,000 fewer tokens in a collection with 100,000 documents.Monitor your index size and adjust your
autocompletetype configuration as needed. You can view MongoDB Search metrics for the following index size and tokenization metrics to help you understand the impact of yourautocompletetype configuration on your index size and resource usage:Search Index SizeSearch Max nGram Fields Indexed
When indexing a string field as the autocomplete type, we recommend that you index the field as the MongoDB Search string type also for the following advantages:
Boost the score of exact matches when using the autocomplete operator.
Query the same field in the same query using the autocomplete operator and another operator that supports string search, such as the text operator. For an example, see the Search Across Multiple Fields example.
Embedded Documents
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 index option to partition your index (supported only on Search Nodes deployments) or shard your cluster.
The exact number of index objects can vary based on the rate of document changes and deletions. The Search Max Number of Lucene Docs 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:
Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.
number of index objects in document = 1 + number of nested embedded documents Multiply the number of index objects per document by the total number of documents in the collection
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 named schools, described in this tutorial, and suppose the collection contains 1000 documents similar to the following:
{ "_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:
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:
Calculate the number of index objects per document.
Number of ``teachers`` embedded documents = up to 2 Total number of index objects per document = 1 + 2 = 3 Multiply by the total number of documents in the collection.
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
The arrays of documents named teachers and teachers.classes are indexed as the embeddedDocuments type with dynamic mappings enabled. Use the following to calculate the index objects:
Calculate the number of index objects per document:
Number of documents = 1 Number of ``teachers`` embedded documents = up to 2 Number of ``classes`` embedded documents = up to 3 Number of index objects per document = 1 + ( 2 x 3 ) = 7 Multiply by the total number of documents in the collection.
Number of documents in the collection = 1000 Number of index objects per document = 7 Total number of index objects: 1000 x 7 = 7000
If your collection has large arrays that might generate 2,100,000,000 index objects, you must shard any clusters that contain indexes with the embeddedDocuments type.
Faceted Search
If you want to filter and facet your data using the same field, we recommend that you index the field as following MongoDB Search types:
For an example of filtering the data by another field for faceting, see the How to Use Facets with MongoDB Search tutorial.
multi Analyzers
Using a multi analyzer to analyze the same field multiple different ways can cause large indexes, especially when analyzing fields with very long values.
Multilingual Search
You can use the MongoDB Search Language Analyzers to index many languages. For the list of languages for which MongoDB Search provides built-in analyzers, see the Language Analyzers. To index and query languages that are currently not in the list of built-in Language Analyzers, you can create a custom analyzer. For an example, see the Custom Language Analyzer Example.
Suppose you have one document for each language in your collection. Consider the following:
You can index the fields separately in the same index using the Language Analyzers. A single index can support multiple languages in the same query.
Alternatively, you can create an index per language, which is useful in isolating the different language documents. Note that each index is a change stream cursor and so this might be expensive to maintain.
If you have the language documents nested inside a parent document, you can create a single index. However, your index definition payload might be large and your query might be complex.
To learn how to do a Multilingual Search, see Multilingual Search Example
Synonym Collections
Inserts and updates to a synonym source collection are fast only if the synonym source collection is small. For best performance, we recommend batching inserts and updates to synonym source collections.
A synonym mapping definition doesn't require additional disk space aside from the disk space utilized by the synonym collection in the database. However, synonym mappings create artifacts in memory and therefore, for synonym collections with many documents, MongoDB Search creates artifacts that occupy more memory.
Search Memory Management
MongoDB Search uses both filesystem cache and JVM heap memory. It stores various objects like query objects, searcher objects, and other temporary data used during indexing and search operations in the JVM heap to process and track the query. It stores memory mapped files such as segment files, dictionary files, and the like in the filesystem cache to enhance its performance, especially when reading index files.
In deployments where both the mongod and mongot processes run on the same node, the memory allocated to the mongod varies based on the cluster tier:
For
M40and higher tier clusters,mongoddedicates 50% or more of the physical RAM for the WiredTiger cache and the remaining memory is reserved for in-memory operations, underlying operation systems, and other system services.For
M30and lower tier clusters,mongoddedicates 25% of the physical RAM for the WiredTiger cache.
Therefore, the memory allocated to mongot is a subset of the total RAM, which can result in resource contention issues between mongod and mongot for not only memory, but also for CPU and Disk IO.
In deployments where the mongot process runs on separate search nodes, Atlas allocates a part of the available RAM to the JVM heap, and uses a small amount of memory processes like monitoring and automation, and the rest of the memory is available for search.
If your search indexes are large and available memory is low, you might observe performance degradation during indexing and querying due to insufficient memory. Search indexes might be large if you enable dynamic mappings in your index for documents with arbitrary keys. This could cause mapping explosions. The excessive memory consumption by mongot can also result in mongot running OOM, which might also crash mongot.
You can use the following metrics to determine if mongot is running OOM:
An increase in the number of
Search Page FaultsandDisk IOPS. This happens if the OS keeps retrieving the required pages from disk and reads them into the RAM.Elevated levels of
Normalized Process/System CPUandIOWait, which can result in degraded performance.
Creating and Updating a MongoDB Search Index
Creating a MongoDB Search index is resource-intensive. The performance of your Atlas cluster might be impacted while the index builds.
Atlas replicates all writes on the collection. This means that for each collection with MongoDB Search indexes, the writes are amplified to the amount of MongoDB Search indexes defined for that collection.
In some instances, your MongoDB Search index must be rebuilt. Rebuilding the MongoDB Search index also consumes resources and might affect database performance. MongoDB Search automatically rebuilds the index in the event of:
Changes to the index definition
Changes to the number of index partitions
Enabling or disabling customer key management, which causes Atlas to perform an initial sync to re-encrypt your cluster data and rebuild your MongoDB Search and MongoDB Vector Search indexes
An initial sync on your cluster, which rebuilds the MongoDB Search indexes on the affected nodes
MongoDB Search version updates that include breaking changes:
Breaking changes are rare.
MongoDB Search provides backwards compatibility for existing indexes in nearly all cases.
When a breaking change does occur, the version update and the resulting index rebuild typically occur during your cluster's maintenance window.
Hardware-related problems such as index corruption
Note
MongoDB Search supports no-downtime indexing, which means you can continue to run search queries while MongoDB Search rebuilds your index. MongoDB Search keeps your old index up-to-date while the new index is being built. You can view the amount of disk space currently used by your index in the Search Disk Space Used metric.
If Atlas detects insufficient disk space to rebuild an index in place, it automatically provisions new nodes in the background, rebuilds the index, and swaps to the new index seamlessly. You can also make storage changes manually as described in Fix Storage Issues, even for clusters with autoscaling enabled.
If you deployed separate Search Nodes, for certain changes such as Java 21 upgrade, Atlas automatically deploys additional Search Nodes for the duration of the index rebuild and you don't need to allocate any additional free disk space.
Once MongoDB Search rebuilds the index, the old index is automatically replaced without any further action from your side.
Eventual Consistency and Indexing Latency
MongoDB Search supports eventual consistency and does not provide any stronger consistency guarantees. This means that data inserted into a MongoDB collection and indexed by MongoDB Search will not be available immediately for $search queries.
MongoDB Search reads data from MongoDB change streams and indexes that data in an asynchronous process. This process is typically very fast, but might sometimes be impacted by replication latency, system resource availability, and index definition complexity. A large number of MongoDB Search indexes might also contribute to replication lag and latency for MongoDB Search indexes.
Highly complex view transformations can increase indexing and query time. This is because the mongod must read the view definition when it filters and transforms the oplog entries during indexing (initial sync and steady state replication), and when it applies those transformations to the returned documents at query-time.
Consider creating a materialized view to avoid extra replication load on Atlas. You can also query the source collection directly to avoid query latency from the view transformation.
Document Mapping Explosions
Mapping explosions occur when MongoDB Search indexes a document with arbitrary keys and you have a dynamic mapping. The mongot process might consume increasing amounts of memory and could crash. If you add too many fields to an index, mapping explosions can occur. To address this issue, you can upgrade your cluster or use a static mapping that does not index all fields in your data.
When searching over fields using a wildcard path, design your search to use a tuple-like schema. If you perform a wildcard path search that uses a key-value schema, MongoDB Search indexes each key as its own field, which can cause mapping explosions.
Example
An example of a key-value schema is as follows:
ruleBuilder: { ruleName1: <data>, ruleName2: <data>, ..... ruleName1025: <data> }
An example of the same data restructured to use a tuple-like schema is as follows:
{ ruleBuilder: [ {name: ruleName1, data: <data>}, {name: ruleName2, data: <data>}, ... {name: ruleName1025, data: <data>} ] }
Storing Source Fields
You can configure fields to store on MongoDB Search and improve performance of subsequent aggregation pipeline stages like $sort, $match, $group, and $skip. Use this optimization if your original documents and matched dataset are so large that a full data lookup is inefficient. To learn more about storing specific fields on MongoDB Search and returning those stored fields only, see Define Stored Source Fields in Your MongoDB Search Index and Return Stored Source Fields.
We recommend storing only the minimum number of fields required for subsequent stages. If necessary, you can use $lookup at the end of the pipeline stage to retrieve entire documents as shown in the Examples. Storing unnecessary fields increases disk utilization and could negatively impact performance during indexing and querying.
Scaling Considerations
MongoDB Search Upgrade
MongoDB Search is deployed on your Atlas cluster. When a new version of MongoDB Search is deployed, your Atlas cluster might experience brief network failures in returning query results. To mitigate issues during deployment and minimize impact to your application, consider the following:
Implement retry logic in your application.
Configure Atlas maintenance windows.
Note
MongoDB Search upgrades start only during the maintenance window and might continue after the maintenance window.
To learn more about the changes in each release, see Atlas Search Changelog.
Scaling Up Indexing Performance
You can scale up your initial sync and steady state indexing for a MongoDB Search index by upgrading your cluster to a higher tier with more cores. MongoDB Search uses a percentage of all available cores to run both initial sync and steady state indexing and performance improves as new cores are made available by upgrading your cluster.
Atlas cluster Configuration Change
If you reconfigure your deployment to use the local NVMe storage type or upscale an NVMe-based cluster, MongoDB Search performs an initial sync of all configured MongoDB Search indexes after each node completes its underlying configuration or upscale action. If the MongoDB Search index initial syncs take longer than the time it took to complete the cluster configuration change, you can't run $search queries until the initial sync completes on all the nodes in your Atlas cluster.
We recommend deploying dedicated Search Nodes to scale your Atlas cluster and $search workloads independently. Dedicated Search Nodes run only the mongot process and therefore improve the availability, performance, and workload balancing of the mongot process.
Scaling your cluster by adding search nodes or by changing the search tier triggers a rebuild of the full MongoDB Search index. However, if your cluster has dedicated search nodes for which you haven't enabled Encryption at Rest using Customer Key Management, Atlas provides the following optimizations:
When you scale your search nodes, Atlas uses a recent copy of your index in S3, Google Cloud Storage, or Azure Blob Storage instead of rebuilding the entire MongoDB Search index on the new node.
For existing nodes, Atlas periodically takes and uploads a new incremental list of index files. Atlas retains index files for up to fourteen (14) days.
Initial Sync in Progress
MongoDB Search starts the initial sync process in the following scenarios:
When you create a new cluster or perform certain upgrades on a cluster, an initial sync process occurs.
If you add shards to a collection with an existing MongoDB Search index, an initial sync occurs on the added shards for that index.
If you shard a collection that already has a MongoDB Search index, an initial sync occurs on shards where the collection begins to exist.
The initial sync process includes the following steps:
The
mongodperforms an initial sync.The
mongotperforms an initial sync, which rebuilds the search indexes.
While a search index rebuilds, you can still perform $search queries on the existing indexed fields. However, MongoDB Search might return an error if you run a $search query against a new field or a node that you've recently created.
Warning
Rolling resyncs cause colocated search instances to fall off the oplog, which affects processes dependant on oplog data. We recommend migrating to dedicated search nodes to avoid this issue.
Check the status of the mongot initial sync using the following steps:
In Atlas, go to the Clusters page for your project.
If it's not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.
If it's not already displayed, select your desired project from the Projects menu in the navigation bar.
In the sidebar, click Clusters under the Database heading.
The Clusters page displays.
In Atlas, go to the Search & Vector Search page for your cluster.
You can go the MongoDB Search page from the Search & Vector Search option, or the Data Explorer.
If it's not already displayed, select the organization that contains your project from the Organizations menu in the navigation bar.
If it's not already displayed, select your project from the Projects menu in the navigation bar.
In the sidebar, click Search & Vector Search under the Database heading.
If you have no clusters, click Create cluster to create one. To learn more, see Create an Atlas Infinite or Atlas Core Cluster.
If your project has multiple clusters, select the cluster you want to use from the Select cluster dropdown, then click Go to Search.
The Search & Vector Search page displays.
If it's not already displayed, select the organization that contains your project from the Organizations menu in the navigation bar.
If it's not already displayed, select your project from the Projects menu in the navigation bar.
In the sidebar, click Data Explorer under the Database heading.
Expand the database and select the collection.
Click the Indexes tab for the collection.
Click the Search and Vector Search link in the banner.
The Search & Vector Search page displays.
Resource Requirements
Index Size and Configuration
Important
If you create a MongoDB Search index for a collection that has or will soon have more than 2.1 billion index objects, use the numPartitions index option to partition your index or shard your cluster. Index partitions are limited to 2.1 billion objects per partition.
Some index configuration options can lead to indexes that take up a significant proportion of your disk space. In some cases, your index could be many times larger than the size of your data. Although this is expected behavior, it's important to be aware of the following indexing-intensive features.
Note
Some limitations apply to MongoDB Search on Free clusters and Flex clusters only. To learn more, see MongoDB Search Search Free and Flex Tier Limitations.
Dynamic vs. Static Mappings
When you create an MongoDB Search index, field mapping defaults to dynamic, which means that MongoDB Search dynamically indexes all the datatypes that can be dynamically indexed in your collection. This can lead to large indexes if you have a large number of fields in your documents, or if you have fields with long string values.
To reduce the size and performance footprint of your index, we recommend using static mappings to specify the fields that you want to index and their types.
store Option
When indexing a text field as the MongoDB Search string type, you can set the store option to false to reduce the size of your index. This prevents MongoDB Search from storing the exact document text as well as the analyzed values in the index. However, setting store to false prevents you from using the highlight option to adds fields to the result set that display search terms in their original context.
Autocomplete
The MongoDB Search autocomplete field type creates indexes that you can use with the autocomplete operator to implement search-as-you-type functionality in your application. However, the autocomplete field type can create large indexes and take longer to build than other field types.
Use the following recommendations to reduce the size and performance footprint of the autocomplete type:
Use the
autocompletetype only for specific fields in static mappings. Using a customtypeSetdefinition to dynamically index string fields as theautocompletetype can apply theautocompletetype too broadly and significantly increase index size and resource usage. In addition, theautocompletetype has specialized, typeahead-oriented scoring behavior suited to specific field indexing, not broad dynamic application. To learn more aboutsimilarity.typescoring with theautocompletetype, see text, phrase, queryString, and autocomplete Operators.Avoid using
nGramas thetokenizationstrategy for theautocompletetype definition, as it creates more tokens for a given string thanedgeGramorrightEdgeGramtokenization.Set a smaller range between the
minGramsandmaxGramsoption values in theautocompletetype definition, which reduces the number of tokens created for each string.Generally, we recommend setting
maxGramsto the character count of the longest word in the field that you want to query. If you are unsure, for English language fields, we recommend starting withmaxGramsvalue of10.Setting a larger value for
minGramscan significantly reduce index size for fields in a collection with many documents. For example, settingminGramsto2instead of1creates 100,000 fewer tokens in a collection with 100,000 documents.Monitor your index size and adjust your
autocompletetype configuration as needed. You can view MongoDB Search metrics for the following index size and tokenization metrics to help you understand the impact of yourautocompletetype configuration on your index size and resource usage:Search Index SizeSearch Max nGram Fields Indexed
When indexing a string field as the autocomplete type, we recommend that you index the field as the MongoDB Search string type also for the following advantages:
Boost the score of exact matches when using the autocomplete operator.
Query the same field in the same query using the autocomplete operator and another operator that supports string search, such as the text operator. For an example, see the Search Across Multiple Fields example.
Embedded Documents
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 index option to partition your index (supported only on Search Nodes deployments) or shard your cluster.
The exact number of index objects can vary based on the rate of document changes and deletions. The Search Max Number of Lucene Docs 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:
Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.
number of index objects in document = 1 + number of nested embedded documents Multiply the number of index objects per document by the total number of documents in the collection
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 named schools, described in this tutorial, and suppose the collection contains 1000 documents similar to the following:
{ "_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:
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:
Calculate the number of index objects per document.
Number of ``teachers`` embedded documents = up to 2 Total number of index objects per document = 1 + 2 = 3 Multiply by the total number of documents in the collection.
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
The arrays of documents named teachers and teachers.classes are indexed as the embeddedDocuments type with dynamic mappings enabled. Use the following to calculate the index objects:
Calculate the number of index objects per document:
Number of documents = 1 Number of ``teachers`` embedded documents = up to 2 Number of ``classes`` embedded documents = up to 3 Number of index objects per document = 1 + ( 2 x 3 ) = 7 Multiply by the total number of documents in the collection.
Number of documents in the collection = 1000 Number of index objects per document = 7 Total number of index objects: 1000 x 7 = 7000
If your collection has large arrays that might generate 2,100,000,000 index objects, you must shard any clusters that contain indexes with the embeddedDocuments type.
Faceted Search
If you want to filter and facet your data using the same field, we recommend that you index the field as following MongoDB Search types:
For an example of filtering the data by another field for faceting, see the How to Use Facets with MongoDB Search tutorial.
multi Analyzers
Using a multi analyzer to analyze the same field multiple different ways can cause large indexes, especially when analyzing fields with very long values.
Multilingual Search
You can use the MongoDB Search Language Analyzers to index many languages. For the list of languages for which MongoDB Search provides built-in analyzers, see the Language Analyzers. To index and query languages that are currently not in the list of built-in Language Analyzers, you can create a custom analyzer. For an example, see the Custom Language Analyzer Example.
Suppose you have one document for each language in your collection. Consider the following:
You can index the fields separately in the same index using the Language Analyzers. A single index can support multiple languages in the same query.
Alternatively, you can create an index per language, which is useful in isolating the different language documents. Note that each index is a change stream cursor and so this might be expensive to maintain.
If you have the language documents nested inside a parent document, you can create a single index. However, your index definition payload might be large and your query might be complex.
To learn how to do a Multilingual Search, see Multilingual Search Example
Synonym Collections
Inserts and updates to a synonym source collection are fast only if the synonym source collection is small. For best performance, we recommend batching inserts and updates to synonym source collections.
A synonym mapping definition doesn't require additional disk space aside from the disk space utilized by the synonym collection in the database. However, synonym mappings create artifacts in memory and therefore, for synonym collections with many documents, MongoDB Search creates artifacts that occupy more memory.
Search Memory Management
MongoDB Search uses both filesystem cache and JVM heap memory. It stores various objects like query objects, searcher objects, and other temporary data used during indexing and search operations in the JVM heap to process and track the query. It stores memory mapped files such as segment files, dictionary files, and the like in the filesystem cache to enhance its performance, especially when reading index files.
In deployments where both the mongod and mongot processes run on the same node, the memory allocated to the mongod varies based on the cluster tier:
For
M40and higher tier clusters,mongoddedicates 50% or more of the physical RAM for the WiredTiger cache and the remaining memory is reserved for in-memory operations, underlying operation systems, and other system services.For
M30and lower tier clusters,mongoddedicates 25% of the physical RAM for the WiredTiger cache.
Therefore, the memory allocated to mongot is a subset of the total RAM, which can result in resource contention issues between mongod and mongot for not only memory, but also for CPU and Disk IO.
In deployments where the mongot process runs on separate search nodes, Atlas allocates a part of the available RAM to the JVM heap, and uses a small amount of memory processes like monitoring and automation, and the rest of the memory is available for search.
If your search indexes are large and available memory is low, you might observe performance degradation during indexing and querying due to insufficient memory. Search indexes might be large if you enable dynamic mappings in your index for documents with arbitrary keys. This could cause mapping explosions. The excessive memory consumption by mongot can also result in mongot running OOM, which might also crash mongot.
You can use the following metrics to determine if mongot is running OOM:
An increase in the number of
Search Page FaultsandDisk IOPS. This happens if the OS keeps retrieving the required pages from disk and reads them into the RAM.Elevated levels of
Normalized Process/System CPUandIOWait, which can result in degraded performance.
Creating and Updating a MongoDB Search Index
Creating a MongoDB Search index is resource-intensive. The performance of your cluster might be impacted while the index builds.
In some instances, your MongoDB Search index must be rebuilt. Rebuilding the MongoDB Search index also consumes resources and might affect database performance. MongoDB Search automatically rebuilds the index in the event of:
Changes to the index definition
Changes to the number of index partitions
An initial sync on your cluster, which rebuilds the MongoDB Search indexes on the affected nodes
MongoDB Search version updates that include breaking changes
Hardware-related problems such as index corruption
Note
MongoDB Search supports no-downtime indexing, which means you can continue to run search queries while MongoDB Search rebuilds your index. MongoDB Search keeps your old index up-to-date while the new index is being built.
If your index rebuild fails due to insufficient disk space, we recommend that you expand your cluster capacity to meet the increased demand.
Once MongoDB Search rebuilds the index, the old index is automatically replaced without any further action from your side.
Eventual Consistency and Indexing Latency
MongoDB Search supports eventual consistency and does not provide any stronger consistency guarantees. This means that data inserted into a MongoDB collection and indexed by MongoDB Search will not be available immediately for $search queries.
MongoDB Search reads data from MongoDB change streams and indexes that data in an asynchronous process. This process is typically very fast, but might sometimes be impacted by replication latency, system resource availability, and index definition complexity. A large number of MongoDB Search indexes might also contribute to replication lag and latency for MongoDB Search indexes.
Highly complex view transformations can increase indexing and query time. This is because the mongod must read the view definition when it filters and transforms the oplog entries during indexing (initial sync and steady state replication), and when it applies those transformations to the returned documents at query-time.
Consider creating a materialized view to avoid extra replication load on Atlas. You can also query the source collection directly to avoid query latency from the view transformation.
Document Mapping Explosions
Mapping explosions occur when MongoDB Search indexes a document with arbitrary keys and you have a dynamic mapping. The mongot process might consume increasing amounts of memory and could crash. If you add too many fields to an index, mapping explosions can occur. To address this issue, you can upgrade your cluster or use a static mapping that does not index all fields in your data.
When searching over fields using a wildcard path, design your search to use a tuple-like schema. If you perform a wildcard path search that uses a key-value schema, MongoDB Search indexes each key as its own field, which can cause mapping explosions.
Example
An example of a key-value schema is as follows:
ruleBuilder: { ruleName1: <data>, ruleName2: <data>, ..... ruleName1025: <data> }
An example of the same data restructured to use a tuple-like schema is as follows:
{ ruleBuilder: [ {name: ruleName1, data: <data>}, {name: ruleName2, data: <data>}, ... {name: ruleName1025, data: <data>} ] }
Storing Source Fields
You can configure fields to store on MongoDB Search and improve performance of subsequent aggregation pipeline stages like $sort, $match, $group, and $skip. Use this optimization if your original documents and matched dataset are so large that a full data lookup is inefficient. To learn more about storing specific fields on MongoDB Search and returning those stored fields only, see Define Stored Source Fields in Your MongoDB Search Index and Return Stored Source Fields.
We recommend storing only the minimum number of fields required for subsequent stages. If necessary, you can use $lookup at the end of the pipeline stage to retrieve entire documents as shown in the Examples. Storing unnecessary fields increases disk utilization and could negatively impact performance during indexing and querying.
Scaling Considerations
MongoDB Search Upgrade
When you deploy a new version of MongoDB Search, your MongoDB cluster might experience brief network failures in returning query results. To mitigate issues during deployment and minimize impact to your application, consider implementing retry logic in your application. For details on sizing, see Introduction to mongot Deployment Sizing.
To learn more about the changes in each release, see MongoDB Search Changelog.
Scaling Up Indexing Performance
You can scale up your initial sync and steady state indexing for a MongoDB Search index by upgrading your cluster to a higher tier with more cores. MongoDB Search uses a percentage of all available cores to run both initial sync and steady state indexing and performance improves as new cores are made available by upgrading your cluster.
Resource Requirements
Index Size and Configuration
Important
If you create a MongoDB Search index for a collection that has or will soon have more than 2.1 billion index objects, use the numPartitions index option to partition your index or shard your cluster. Index partitions are limited to 2.1 billion objects per partition.
Some index configuration options can lead to indexes that take up a significant proportion of your disk space. In some cases, your index could be many times larger than the size of your data. Although this is expected behavior, it's important to be aware of the following indexing-intensive features.
Dynamic vs. Static Mappings
When you create an MongoDB Search index, field mapping defaults to dynamic, which means that MongoDB Search dynamically indexes all the datatypes that can be dynamically indexed in your collection. This can lead to large indexes if you have a large number of fields in your documents, or if you have fields with long string values.
To reduce the size and performance footprint of your index, we recommend using static mappings to specify the fields that you want to index and their types.
store Option
When indexing a text field as the MongoDB Search string type, you can set the store option to false to reduce the size of your index. This prevents MongoDB Search from storing the exact document text as well as the analyzed values in the index. However, setting store to false prevents you from using the highlight option to adds fields to the result set that display search terms in their original context.
Autocomplete
The MongoDB Search autocomplete field type creates indexes that you can use with the autocomplete operator to implement search-as-you-type functionality in your application. However, the autocomplete field type can create large indexes and take longer to build than other field types.
Use the following recommendations to reduce the size and performance footprint of the autocomplete type:
Use the
autocompletetype only for specific fields in static mappings. Using a customtypeSetdefinition to dynamically index string fields as theautocompletetype can apply theautocompletetype too broadly and significantly increase index size and resource usage. In addition, theautocompletetype has specialized, typeahead-oriented scoring behavior suited to specific field indexing, not broad dynamic application. To learn more aboutsimilarity.typescoring with theautocompletetype, see text, phrase, queryString, and autocomplete Operators.Avoid using
nGramas thetokenizationstrategy for theautocompletetype definition, as it creates more tokens for a given string thanedgeGramorrightEdgeGramtokenization.Set a smaller range between the
minGramsandmaxGramsoption values in theautocompletetype definition, which reduces the number of tokens created for each string.Generally, we recommend setting
maxGramsto the character count of the longest word in the field that you want to query. If you are unsure, for English language fields, we recommend starting withmaxGramsvalue of10.Setting a larger value for
minGramscan significantly reduce index size for fields in a collection with many documents. For example, settingminGramsto2instead of1creates 100,000 fewer tokens in a collection with 100,000 documents.
When indexing a string field as the autocomplete type, we recommend that you index the field as the MongoDB Search string type also for the following advantages:
Boost the score of exact matches when using the autocomplete operator.
Query the same field in the same query using the autocomplete operator and another operator that supports string search, such as the text operator. For an example, see the Search Across Multiple Fields example.
Embedded Documents
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 index option to partition your index (supported only on Search Nodes deployments) or shard your cluster.
The exact number of index objects can vary based on the rate of document changes and deletions. The Search Max Number of Lucene Docs 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:
Calculate the number of index objects per document. For every level of nesting, each embedded document counts as a separate index object.
number of index objects in document = 1 + number of nested embedded documents Multiply the number of index objects per document by the total number of documents in the collection
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 named schools, described in this tutorial, and suppose the collection contains 1000 documents similar to the following:
{ "_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:
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:
Calculate the number of index objects per document.
Number of ``teachers`` embedded documents = up to 2 Total number of index objects per document = 1 + 2 = 3 Multiply by the total number of documents in the collection.
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
The arrays of documents named teachers and teachers.classes are indexed as the embeddedDocuments type with dynamic mappings enabled. Use the following to calculate the index objects:
Calculate the number of index objects per document:
Number of documents = 1 Number of ``teachers`` embedded documents = up to 2 Number of ``classes`` embedded documents = up to 3 Number of index objects per document = 1 + ( 2 x 3 ) = 7 Multiply by the total number of documents in the collection.
Number of documents in the collection = 1000 Number of index objects per document = 7 Total number of index objects: 1000 x 7 = 7000
If your collection has large arrays that might generate 2,100,000,000 index objects, you must shard any clusters that contain indexes with the embeddedDocuments type.
Faceted Search
If you want to filter and facet your data using the same field, we recommend that you index the field as following MongoDB Search types:
For an example of filtering the data by another field for faceting, see the How to Use Facets with MongoDB Search tutorial.
multi Analyzers
Using a multi analyzer to analyze the same field multiple different ways can cause large indexes, especially when analyzing fields with very long values.
Multilingual Search
You can use the MongoDB Search Language Analyzers to index many languages. For the list of languages for which MongoDB Search provides built-in analyzers, see the Language Analyzers. To index and query languages that are currently not in the list of built-in Language Analyzers, you can create a custom analyzer. For an example, see the Custom Language Analyzer Example.
Suppose you have one document for each language in your collection. Consider the following:
You can index the fields separately in the same index using the Language Analyzers. A single index can support multiple languages in the same query.
Alternatively, you can create an index per language, which is useful in isolating the different language documents. Note that each index is a change stream cursor and so this might be expensive to maintain.
If you have the language documents nested inside a parent document, you can create a single index. However, your index definition payload might be large and your query might be complex.
To learn how to do a Multilingual Search, see Multilingual Search Example
Synonym Collections
Inserts and updates to a synonym source collection are fast only if the synonym source collection is small. For best performance, we recommend batching inserts and updates to synonym source collections.
A synonym mapping definition doesn't require additional disk space aside from the disk space utilized by the synonym collection in the database. However, synonym mappings create artifacts in memory and therefore, for synonym collections with many documents, MongoDB Search creates artifacts that occupy more memory.
Search Memory Management
MongoDB Search uses both filesystem cache and JVM heap memory. It stores various objects like query objects, searcher objects, and other temporary data used during indexing and search operations in the JVM heap to process and track the query. It stores memory mapped files such as segment files, dictionary files, and the like in the filesystem cache to enhance its performance, especially when reading index files.
In deployments where both the mongod and mongot processes run on the same node, the memory allocated to the mongod varies based on the hardware.
The memory allocated to mongot is a subset of the total RAM, which can result in resource contention issues between mongod and mongot for not only memory, but also for CPU and Disk IO. For guidance, see Hardware Considerations for mongot Deployments.
In deployments where the mongot process runs on separate search nodes, Atlas allocates a part of the available RAM to the JVM heap, and uses a small amount of memory processes like monitoring and automation, and the rest of the memory is available for search.
If your search indexes are large and available memory is low, you might observe performance degradation during indexing and querying due to insufficient memory. Search indexes might be large if you enable dynamic mappings in your index for documents with arbitrary keys. This could cause mapping explosions. The excessive memory consumption by mongot can also result in mongot running OOM, which might also crash mongot.
Creating and Updating a MongoDB Search Index
Creating a MongoDB Search index is resource-intensive. The performance of your cluster might be impacted while the index builds.
In some instances, your MongoDB Search index must be rebuilt. Rebuilding the MongoDB Search index also consumes resources and might affect database performance. MongoDB Search automatically rebuilds the index in the event of:
Changes to the index definition
Changes to the number of index partitions
An initial sync on your cluster, which rebuilds the MongoDB Search indexes on the affected nodes
MongoDB Search version updates that include breaking changes
Hardware-related problems such as index corruption
Note
MongoDB Search supports no-downtime indexing, which means you can continue to run search queries while MongoDB Search rebuilds your index. MongoDB Search keeps your old index up-to-date while the new index is being built.
If your index rebuild fails due to insufficient disk space, we recommend that you expand your cluster capacity to meet the increased demand.
Once MongoDB Search rebuilds the index, the old index is automatically replaced without any further action from your side.
Eventual Consistency and Indexing Latency
MongoDB Search supports eventual consistency and does not provide any stronger consistency guarantees. This means that data inserted into a MongoDB collection and indexed by MongoDB Search will not be available immediately for $search queries.
MongoDB Search reads data from MongoDB change streams and indexes that data in an asynchronous process. This process is typically very fast, but might sometimes be impacted by replication latency, system resource availability, and index definition complexity. A large number of MongoDB Search indexes might also contribute to replication lag and latency for MongoDB Search indexes.
Highly complex view transformations can increase indexing and query time. This is because the mongod must read the view definition when it filters and transforms the oplog entries during indexing (initial sync and steady state replication), and when it applies those transformations to the returned documents at query-time.
Consider creating a materialized view to avoid extra replication load on Atlas. You can also query the source collection directly to avoid query latency from the view transformation.
Document Mapping Explosions
Mapping explosions occur when MongoDB Search indexes a document with arbitrary keys and you have a dynamic mapping. The mongot process might consume increasing amounts of memory and could crash. If you add too many fields to an index, mapping explosions can occur. To address this issue, you can upgrade your cluster or use a static mapping that does not index all fields in your data.
When searching over fields using a wildcard path, design your search to use a tuple-like schema. If you perform a wildcard path search that uses a key-value schema, MongoDB Search indexes each key as its own field, which can cause mapping explosions.
Example
An example of a key-value schema is as follows:
ruleBuilder: { ruleName1: <data>, ruleName2: <data>, ..... ruleName1025: <data> }
An example of the same data restructured to use a tuple-like schema is as follows:
{ ruleBuilder: [ {name: ruleName1, data: <data>}, {name: ruleName2, data: <data>}, ... {name: ruleName1025, data: <data>} ] }
Storing Source Fields
You can configure fields to store on MongoDB Search and improve performance of subsequent aggregation pipeline stages like $sort, $match, $group, and $skip. Use this optimization if your original documents and matched dataset are so large that a full data lookup is inefficient. To learn more about storing specific fields on MongoDB Search and returning those stored fields only, see Define Stored Source Fields in Your MongoDB Search Index and Return Stored Source Fields.
We recommend storing only the minimum number of fields required for subsequent stages. If necessary, you can use $lookup at the end of the pipeline stage to retrieve entire documents as shown in the Examples. Storing unnecessary fields increases disk utilization and could negatively impact performance during indexing and querying. For guidance, see Disk Sizing Guideline.
Scaling Considerations
MongoDB Search Upgrade
When you deploy a new version of MongoDB Search, your MongoDB cluster might experience brief network failures in returning query results. To mitigate issues during deployment and minimize impact to your application, consider implementing retry logic in your application. For details on sizing, see Introduction to mongot Deployment Sizing.
To learn more about the changes in each release, see MongoDB Search Changelog.
Scaling Up Indexing Performance
You can scale up your initial sync and steady state indexing for a MongoDB Search index by upgrading your CPU and RAM. MongoDB Search uses a percentage of all available cores to run both initial sync and steady state indexing and performance improves as new cores are made available by upgrading your cluster.
Initial Sync in Progress
MongoDB Search starts the initial sync process in the following scenarios:
When you create a new index, the
mongotprocess performs an initial sync to build the index.If you add shards to a collection with an existing MongoDB Search index, an initial sync occurs on the newly added shards for that index. Each shard's MongoDB Search index contains only the documents from the collection that exist on that shard.
If the
mongodoplog rolls over beforemongotcatches up,mongotfalls out of steady state replication and performs an initial sync to rebuild the index.
The index isn't queryable while its initial sync runs. To monitor the progress of an initial sync, review the mongot_replication_mongodb_indexManagerState metric, which reports the INITIAL_SYNC state while the sync runs and the STEADY_STATE state after it completes. To learn more, see Metrics Reference for mongot.
If an initial sync takes longer than expected or an index repeatedly returns to the INITIAL_SYNC state, see the following troubleshooting topics: