Mongoose - What does the exec function do?

I came across a piece of Mongoose code that included a query findOne and then an exec() function.

Ive never seen that method in Javascript before? What does it do exactly?

Answers:

Answer

Basically when using mongoose, documents can be retrieved using helpers. Every model method that accepts query conditions can be executed by means of a callback or the exec method.

callback:

User.findOne({ name: 'daniel' }, function (err, user) {
  //
});

exec:

User
  .findOne({ name: 'daniel' })
  .exec(function (err, user) {
      //
  });

Therefore when you don't pass a callback you can build a query and eventually execute it.

You can find additional info in the mongoose docs.

UPDATE

Something to note when using Promises in combination with Mongoose async operations is that Mongoose queries are not Promises. Queries do return a thenable, but if you need a real Promise you should use the exec method. More information can be found here.

During the update I noticed I didn't explicitly answer the question:

Ive never seen that method in Javascript before? What does it do exactly?

Well it's not a native JavaScript method, but part of the Mongoose API.

Answer

Daniel has answered this quite beautifully. To elaborate on an exhaustive list of ways to build and execute queries, look at the following use cases:

Query Building

Mongoose will not execute a query until then or exec has been called upon it. This is very useful when building complex queries. Some examples can include using the populate and aggregate functions.

User.find({name: 'John'}) // Will not execute

Execution via callback

Although disliked by many due to its nesting nature, queries can be executed by providing the optional callback.

User.find({name: 'John'}, (err, res) => {}) // Will execute

Then API as a Promises/A+

Mongoose queries do provide a then function. This is not to be confused with regular promises. Simply put, the Promises/A+ specification requires a then function to work much like how we're used to with promises.

User.find({name: 'John'}).then(); // Will execute
Promise.all([User.find({name: 'John'}), User.find({name: 'Bob'})]) // Will execute all queries in parallel

The exec function

From Mongoose docs If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise
Answer

exec() will return a promise if no callback is provided. So the following pattern is very convenient and generic - it can handle callbacks or promises nicely:

function findAll(query, populate, cb) {

  let q = Response.find(query);

  if (populate && populate.length > 0) {
    q = q.populate(populate);
  }

  // cb is optional, will return promise if cb == null
  return q.lean().exec(cb);

}

I recommend using Bluebird promises with Mongoose, to do that, use this call:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.