Learn Mongoose find() by Example

Jul 10, 2019

In Mongoose, the Model.find() function is the primary tool for querying the database. The first parameter to Model.find() is a filter object. MongoDB will search for all documents that match the filter. If you pass an empty filter, MongoDB will return all documents.

In this tutorial, you'll see how to execute common queries in Mongoose by structuring the filter object using MongoDB query operators.

Equality Checks

Suppose you have a Character model that contains 5 characters from Star Trek: The Next Generation.

const Character = mongoose.model('Character', mongoose.Schema({
  name: String,
  age: Number,
  rank: String
}));

await Character.create([
  { name: 'Jean-Luc Picard', age: 59, rank: 'Captain' },
  { name: 'William Riker', age: 29, rank: 'Commander' },
  { name: 'Deanna Troi', age: 28, rank: 'Lieutenant Commander' },
  { name: 'Geordi La Forge', age: 29, rank: 'Lieutenant' },
  { name: 'Worf', age: 24, rank: 'Lieutenant' }
]);

Suppose you want to find all characters whose rank is 'Lieutenant'. The way to do this is to pass { rank: 'Lieutenant' } as the filter.

const docs = await Character.find({ rank: 'Lieutenant' });

// MongoDB may return the docs in any order unless you explicitly sort
docs.map(doc => doc.name).sort(); // ['Geordi La Forge', 'Worf']

You can also query by age. For example, the below query will find all characters whose age is 29.

const docs = await Character.find({ age: 29 });

docs.map(doc => doc.name).sort(); // ['Geordi La Forge', 'William Riker']

The above examples don't use any query operators. If you set the value of rank to an object with a $eq property, you get an equivalent query, but using a query operator. The $eq query operator is usually not useful. But this example demonstrates the query operator syntax, which you need for structuring non-trivial queries.

// Equivalent to `{ rank: 'Lieutenant' }`. `$eq` is an example of
// a "query operator"
const docs = await Character.find({ rank: { $eq: 'Lieutenant' } });

docs.map(doc => doc.name).sort(); // ['Geordi La Forge', 'Worf']

Comparisons

The $eq query operator checks exact equality. There are also comparison query operators like $gt and $lt. For example, suppose you want to find all characters whose age is strictly less than 29. You can use the $lt query operator as shown below.

const docs = await Character.find({ age: { $lt: 29 } });

docs.map(doc => doc.name).sort(); // ['Deanna Troi', 'Worf']

Suppose you wanted to find all characters whose age is at least 29. For that, you should use the $gte query operator.

const docs = await Character.find({ age: { $gte: 29 } });

// ['Geordi La Forge', 'Jean-Luc Picard', 'William Riker']
docs.map(doc => doc.name).sort();

The comparison operators $lt, $gt, $lte, and $gte work with more than just numbers. You can also use them on strings, dates, and other types. MongoDB compares strings using unicode order. If that order doesn't work for you, you can configure it using MongoDB collations.

const docs = await Character.find({ name: { $lte: 'Geordi La Forge' } });

// ['Deanna Troi', 'Geordi La Forge']
docs.map(doc => doc.name).sort();

Regular Expressions

Suppose you want to find characters whose rank contains 'Commander'. In SQL, you would use the LIKE operator. In Mongoose, you can simply query by a regular expression as shown below.

const docs = await Character.find({ rank: /Commander/ });

// ['Deanna Troi', 'William Riker']
docs.map(doc => doc.name).sort();

Equivalently, you can use the $regex query operator. This enables you to pass the regular expression as a string, which is convenient if you're getting the query from an HTTP request.

const docs = await Character.find({ rank: { $regex: 'Commander' } });

// ['Deanna Troi', 'William Riker']
docs.map(doc => doc.name).sort();

Composition with $and and $or

If you set multiple filter properties, MongoDB finds documents that match all the filter properties. For example, the below query will find all characters whose age is at least 29 and whose rank equals 'Commander'.

const docs = await Character.find({
  age: { $gte: 29 },
  rank: 'Commander'
});

// ['William Riker']
docs.map(doc => doc.name);

Suppose you want to find characters whose age is at least 29 or whose rank equals 'Commander'. You would need the $or query operator.

const docs = await Character.find({
  $or: [
    { age: { $gte: 29 } },
    { rank: 'Commander' }
  ]
});

// ['Geordi La Forge', 'Jean-Luc Picard', 'William Riker']
docs.map(doc => doc.name).sort();

There is also a $and query operator. You will rarely need to use the $and query operator. The primary use case for $and is to compose multiple $or operators. For example, suppose you want to find characters whose that satisfy both of the below conditions:

  1. age at least 29 or whose rank equals 'Commander'
  2. name starts with a letter before 'D' or after 'W'.
const docs = await Character.find({
  $and: [
    {
      $or: [
        { age: { $gte: 29 } },
        { rank: 'Commander' }
      ]
    },
    {
      $or: [
        { name: { $lte: 'D' } },
        { name: { $gte: 'W' } }
      ]
    }
  ]
});

// ['William Riker']
docs.map(doc => doc.name).sort();

Want to become your team's MongoDB expert? "Mastering Mongoose" distills 8 years of hard-earned lessons building Mongoose apps at scale into 153 pages. That means you can learn what you need to know to build production-ready full-stack apps with Node.js and MongoDB in a few days. Get your copy!

Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Mongoose Tutorials