An Introduction to Queries in Mongoose
Many Mongoose model functions, like find()
, return a Mongoose query. The Mongoose Query class provides a chaining interface for finding, updating, and deleting documents.
const Character = mongoose.model('Character', Schema({
name: String,
age: Number
}));
const query = Character.find();
query instanceof mongoose.Query; // true
// Execute the query
const docs = await query;
Chaining
The first parameter to Model.find()
is called the query filter. When you
call find()
, MongoDB will return all documents that match the query filter.
You can use Mongoose's numerous query helpers to build up query filters. Just
make sure you specify the property name to add to the filter using where()
.
let docs = await Character.find().
// `where()` specifies the name of the property
where('name').
// and then the query helper `in()` specifies that `name`
// must be one of the 2 values in the array
in(['Jean-Luc Picard', 'Will Riker']);
// Equivalent query, but with the filter expressed as an object rather
// than using chaining
docs = await Character.find({
name: { $in: ['Jean-Luc Picard', 'Will Riker'] }
});
Chainable operations let you add to the current query filter. You can get the
query's current filter using the Query#getFilter()
function.
const query = Character.find().
where('name').in(['Jean-Luc Picard', 'Will Riker']);
// `{ name: { $in: ['Jean-Luc Picard', 'Will Riker'] } }`
query.getFilter();
Here's a list of several useful query helpers:
lt(value)
,gt(value)
: specify that a property must be less than (lt()
) or greater than (gt()
) a value.value
can be a number, string, or date.lte(value)
,gte(value)
: specify that a property must be greater than or equal to (gte()
), or less than or equal to (gte()
), a value.in(arr)
: specify that a property must be equal to one of the values specified inarr
nin(arr)
: specify that a property must not equal any of the values specified inarr
eq(val)
: specify that a property must be equal toval
ne(val)
: specify that a property must not be equal toval
regex(re)
: specify that a property must be a string that matchesre
You can chain arbitrarily many where()
calls and query helpers to build up
your query. For example:
const docs = await Character.find().
// `name` must match the regular expression
where('name').regex(/picard/i).
// `age` must be between 29 and 59
where('age').gte(29).lte(59);
Executing
Mongoose queries are not promises. The key difference is that Mongoose doesn't actually send your query to the server until you explicitly execute the query. There's 2 ways to execute a query:
Query#exec()
: executes the query and returns a native JavaScript promise.
const promise = Character.find().exec();
promise instanceof Promise; // true
promise instanceof mongoose.Query; // false
const docs = await promise;
Query#then()
andQuery#catch()
: provides a pseudo-promise API for queries, so you canawait
on a Mongoose query. You can also use promise chaining with Mongoose queries as shown below.
return Character.find().then(docs => {
docs; // List of docs
});