Mongoose: Find Documents That Contain a Given Value

Updated: December 30, 2023 By: Guest Contributor Post a comment

Introduction

When working with Mongoose, a data modeling library for MongoDB and Node.js, developers often need to retrieve documents based on certain criteria. One common task is to find documents where a particular field contains a specific value. This tutorial will walk you through various ways to achieve this, using the latest ES6+ syntax and async/await patterns for clean and readable code.

We’ll start with basic queries using find, and gradually move on to more sophisticated queries, including those employing regular expressions and array search. By the end of this tutorial, you should feel confident in retrieving documents to fit a wide range of use cases.

Let’s get started by setting up Mongoose and the model we’ll be using for our examples.

Getting Started

Ensure you have Node.js installed, then set up a new project and install mongoose:

npm init -y
npm install mongoose

Create a file named db.js and establish a connection to MongoDB:

import mongoose from 'mongoose';
mongoose.connect('mongodb://localhost/database_name', {useNewUrlParser: true, useUnifiedTopology: true});

Define a schema and model for our examples. In this case, let’s create one for blog posts:

import { Schema, model } from 'mongoose';

const blogPostSchema = new Schema({
  title: String,
  content: String,
  tags: [String],
  publishedDate: Date
});

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

With the initial setup complete, we can begin exploring various find operations.

Basic Queries

The most straightforward use case is finding documents where a field exactly matches a given value. In Mongoose, this is achieved using the find method:

async function findPostsByTitle(title) {
  try {
    const results = await BlogPost.find({ title: title });
    return results;
  } catch (error) {
    console.error('Error finding posts:', error);
  }
}

// Use the function
findPostsByTitle('Node.js Basics').then(console.log);

ES6+ provides syntactic sugar for properties where the key and value are the same, allowing us to simplify the query:

const results = await BlogPost.find({ title });

Partial Text Search

To find documents containing a given substring in a text field, you can use regular expressions:

async function findPostsContainingText(text) {
  try {
    const regex = new RegExp(text, 'i'); // The 'i' flag makes it case-insensitive
    const results = await BlogPost.find({ content: { $regex: regex } });
    return results;
  } catch (error) {
    console.error('Error finding posts with text:', error);
  }
}

// Usage
findPostsContainingText('mongoose').then(console.log);

Searching Within Arrays

The $in operator allows querying multiple values within an array field:

async function findPostsByTags(tagsArray) {
  try {
    const results = await BlogPost.find({ tags: { $in: tagsArray } });
    return results;
  } catch (error) {
    console.error('Error finding posts by tags:', error);
  }
}

// Using the functionindPostsByTags(['tutorial', 'JavaScript']).then(console.log);

Advanced Query Techniques

If we want to combine criteria, the logical operators $and and $or are extremely helpful:

async function findPublishedAfterDateWithTags(date, tagsArray) {
  try {
    const results = await BlogPost.find({
      publishedDate: { $gte: date },
      tags: { $in: tagsArray }
    });
    return results;
  } catch (error) {
    console.error('Error finding posts:', error);
  }
}

// Use the function
findPublishedAfterDateWithTags(new Date('2021-01-01'), ['news']).then(console.log);

An example of complex searching criteria, can be attained by pushing to the next level using projection, sorting, and pagination:

async function findAndSort(tagsArray, skip, limit) {
  try {
    const results = await BlogPost.find({text: {$regex: /matchtext/i})
      .select('title publishedDate') // Projection
      .sort({ publishedDate: -1 }) // Sorting
      .skip(skip) // Pagination
      .limit(limit);
    return results;
  } catch (error) {
    console.error('Error finding and sorting posts:', error);
  }
}

// Example usage:
findAndSort(['tutorial'], 0, 10).then(console.log);

Conclusion

In this tutorial, we covered the basics of finding documents in Mongoose where a field contains a specific value using different approaches. Remember, efficient database querying not only involves knowing various query techniques but also includes understanding how to harness the capabilities of indexing and MongoDB’s powerful aggregation framework for optimal performance.

Take the time to explore the Mongoose API further, and experiment with creating more complex queries tailored to your data needs. With this knowledge in your toolkit, Mongoose will serve as an even more powerful ally in your Node.js development endeavors.