Skip to content

MongoDB - Text Search

MongoDB provides powerful full-text search capabilities through text indexes. This feature allows you to efficiently search for words and phrases within string content. It includes case-insensitivity, support for multiple languages, and stemming (e.g., searching for ‘running’ also finds ‘run’).

First, you need to define a text index on the field(s) you want to search. Let’s consider a collection of blog posts.

// Insert sample data
db.posts.insertMany([
{
"_id": 1,
"content": "An introduction to the powerful features of MongoDB.",
"tags": ["mongodb", "database", "nosql"]
},
{
"_id": 2,
"content": "MongoDB text search is a powerful tool for developers.",
"tags": ["search", "full-text", "mongodb"]
},
{
"_id": 3,
"content": "We are exploring advanced database indexing techniques.",
"tags": ["database", "performance"]
}
]);
// Create a text index on the 'content' field
db.posts.createIndex({ content: "text" });
// You can also index multiple fields
// db.posts.createIndex({ content: "text", tags: "text" });

The index will be created in the background. MongoDB will parse the content, drop common stop words (like ‘a’, ‘the’, ‘is’), and stem words to their root form.

To search using the index, you use the $text operator with $search.

This query finds all posts containing the word ‘mongodb’ or ‘powerful’.

// Search for posts containing 'mongodb' or 'powerful'
db.posts.find({ $text: { $search: "mongodb powerful" } });

To search for an exact phrase, enclose it in double quotes.

// Search for the exact phrase "powerful tool"
db.posts.find({ $text: { $search: '"powerful tool"' } });

You can exclude results containing a specific word by prefixing it with a hyphen -.

// Search for 'database' but not 'nosql'
db.posts.find({ $text: { $search: "database -nosql" } });

A key feature of text search is the ability to rank results by relevance. You can access the relevance score using $meta: "textScore" and sort by it.

// Find posts about 'mongodb' and sort them by relevance
db.posts.find(
{ $text: { $search: "mongodb" } },
{ score: { $meta: "textScore" } } // Project the score into a 'score' field
).sort(
{ score: { $meta: "textScore" } } // Sort by the calculated text score
);

This query will return documents that match ‘mongodb’ best at the top of the result set.

If you no longer need the index, you can drop it by its name. First, find the index name using getIndexes().

> db.posts.getIndexes()
// The text index name is typically fieldName_text, e.g., 'content_text'
> db.posts.dropIndex("content_text")
{
"nIndexesWas": 2,
"ok": 1
}