Photo by Yosuke Ota on Unsplash

On this page

This chapter follows Transactions in MongoDB.

Regex and $text on self-hosted Community

Regex on arbitrary fields ({ title: { $regex: /mongo/i } }) is flexible but often cannot use indexes efficiently unless anchored to a prefix.

Text indexes support the $text operator and a single text index per collection:

db.articles.createIndex({ title: 'text', body: 'text' })
db.articles.find({ $text: { $search: 'aggregation framework' } })

Text search is language-aware but limited compared to dedicated search engines—no rich facets, fuzzy tuning, or autocomplete in one package.

Use regex and $text for simple filters; move to Atlas Search when relevance ranking and analyzers matter.

Atlas Search overview

Atlas Search (Lucene-backed) runs on Atlas and on Atlas Local (mongodb/mongodb-atlas-local) for development. It uses search indexes separate from standard MongoDB indexes and the $search aggregation stage.

Run Atlas Local for this chapter:

Terminal window
docker run -p 27017:27017 -p 8080:8080 mongodb/mongodb-atlas-local

Connect with the URI printed in the container logs.

Define a search index

Example index JSON (stored on the search node):

{
"mappings": {
"dynamic": false,
"fields": {
"title": { "type": "string", "analyzer": "lucene.standard" },
"body": { "type": "string", "analyzer": "lucene.english" }
}
}
}

Create from TypeScript on Atlas (Search Index API or createSearchIndexes command depending on deployment):

await db.collection('articles').createSearchIndex({
name: 'articles_default',
definition: {
mappings: {
dynamic: false,
fields: {
title: { type: 'string', analyzer: 'lucene.standard' },
body: { type: 'string', analyzer: 'lucene.english' },
},
},
},
});

Wait until index status is READY before querying.

$search queries

Basic text search:

db.articles.aggregate([
{
$search: {
index: 'articles_default',
text: { query: 'vector embeddings', path: ['title', 'body'] },
},
},
{ $limit: 10 },
{ $project: { title: 1, score: { $meta: 'searchScore' } } },
])

Compound boolean queries combine must/should/mustNot:

{
$search: {
index: 'articles_default',
compound: {
must: [{ text: { query: 'mongodb', path: 'title' } }],
should: [{ text: { query: 'atlas', path: 'body', fuzzy: { maxEdits: 1 } } }],
},
},
}

Autocomplete uses the autocomplete field type in the index definition and matching operator in queries.

Highlights, facets, and scoring

Add highlights:

{
$search: {
index: 'articles_default',
text: { query: 'pagination', path: 'body' },
highlight: { path: 'body' },
},
}

Faceted counts with $searchMeta:

{
$searchMeta: {
index: 'articles_default',
facet: {
operator: { text: { query: 'database', path: 'body' } },
facets: { categoryFacet: { type: 'string', path: 'category', numBuckets: 10 } },
},
},
}

Project searchScore via { $meta: 'searchScore' } to sort by relevance.

Paginate with searchAfter

For stable cursor pagination through search results, use searchAfter with the sort values from the previous page (similar in spirit to keyset pagination):

{
$search: {
index: 'articles_default',
text: { query: 'mongodb', path: 'title' },
sort: { score: { $meta: 'searchScore' }, _id: 1 },
searchAfter: '<token from previous page>',
},
}

Next: Vector search and embeddings in MongoDB.

Check your understanding

Question 1 of 5

0 of 5 checked

  1. 1. What limitation does the article note for regex on arbitrary fields?

Search articles

Type a word to search published articles.

Open the search page