Sling Academy
Home/Node.js/Mongoose: Search documents by keywords (text search)

Mongoose: Search documents by keywords (text search)

Last updated: December 30, 2023

Searching documents by keywords is a common requirement for modern applications. Mongoose, as a powerful Node.js ORM for MongoDB, offers capabilities to perform efficient text searches on document fields.

Enabling Text Search in Mongoose

To begin performing text searches with Mongoose, we need to create a text index on the fields we want to search. The following example shows how to define a text index in a Mongoose schema:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const blogPostSchema = new Schema({
  title: { type: String, required: true },
  content: String
});

blogPostSchema.index({ title: 'text', content: 'text' });

const BlogPost = mongoose.model('BlogPost', blogPostSchema);

After setting up the schema, you can perform a basic text search using the $text operator:

BlogPost.find({ $text: { $search: 'keyword' } })
   .then(posts => {
     console.log(posts);
   })
   .catch(err => {
     console.error(err);
   });
 

Using Text Score

With text search, Mongoose can also return a relevance score:

BlogPost.find({ $text: { $search: 'keyword' } },
   { score: { $meta: 'textScore' } })
   .sort({ score: { $meta: 'textScore' } })
   .then(posts => {
     console.log(posts);
   })
   .catch(err => {
     console.error(err);
   });
 

Advanced Text Search Techniques

For more complex search requirements, Mongoose text search supports phrases, negations, and more.

Searching for Phrases

To search for an exact phrase, use double quotes around the phrase:

BlogPost.find({ $text: { $search: '"Specific phrase"' } })
   .then(posts => {
     console.log(posts);
   })
   .catch(err => {
     console.error(err);
   });

Excluding Words

You can exclude documents that contain a specific word by prefixing a minus sign (-) to the word:

BlogPost.find({ $text: { $search: 'keyword -unwanted' } })
   .then(posts => {
     console.log(posts);
   })
   .catch(err => {
     console.error(err);
   });
 

Combining Text Search with Other Queries

Text search can be combined with other Mongoose query operators to refine results.

Combining with Other Criteria

Let’s find documents based on text search and a date range:

BlogPost.find({
   $text: { $search: 'keyword' },
   createdAt: {
     $gte: new Date('2024-01-01'),
     $lt: new Date('2024-12-31')
   }
 })
 .then(posts => {
   console.log(posts);
 })
 .catch(err => {
   console.error(err);
 });
 

Using RegExp for Partial Matches

While not a full text search, for partial matching, regular expressions can be used:

BlogPost.find({ title: { $regex: '.*key.*', $options: 'i' } })
 .then(posts => {
   console.log(posts);
 })
 .catch(err => {
   console.error(err);
 });
 

Final Words

While Mongoose text search is powerful, it’s essential to consider its impact on performance, especially with large datasets. Indexing, query optimization, and database design play significant roles in the search performance.

Text search in Mongoose is a robust feature that can significantly enhance the user experience by allowing users to search through documents using keywords. Setting up text indexes and using the right query techniques are necessary for building efficient search capabilities into your applications.

Next Article: Mongoose: Compare two dates in a query (before, after, between)

Previous Article: Mongoose: Find Documents That Contain a Given String

Series: Mongoose.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates