Mongoose - What does the exec function do?

JavascriptMongoose

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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][1].

[1]:http://mongoosejs.com/docs/queries.html "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.

Solution 2 - Javascript

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

Solution 3 - Javascript

I never use exec() function to complete a CRUD(Create, Read, Update, Delete) on a model. When I want CRUD on a model, I use it like this:

const user = await UserModel.findOne(userCondition);

And it always does the job. So I wondered "what does exec() use for"? As I searched in mongoose document, I found the answer here.

> Should You Use exec() With await?

And here is the story.
You have two ways to execute a query on a model. Using callback or using exec() function. "But" you can use await too. exec() function returns a promise, that you can use it with then() or async/await to execute a query on a model "asynchronous". So the question is "If I can just use user = await UserModel.find() and it works currectly, so why should I use exec() function?". The answer that you can find in the document is:

There are two difference between using await with exec() or without it.

  • As a functionality point of view, there is no difference between using await with exec() or without it. Just when you call a query without exec() or callback, it returns a thenable which is something like promise but it's not a promise.(You can find the difference here). But when you use exec() to run a query, you get exactly a promise as response.
// returns a thenable as response that is not a promise, but you can use await and then() with it.
const user = await UserModel.findOne(userCondition);

// returns exactly a promise.
const user = await UserModel.findOne(userCondition).exec(); 
  • Another difference is, if you use await with exec() you get a better "stack trace" if you catch any error in executing queries. So:

    These two line, do the same thing:
const user = await UserModel.findOne(userCondition);

// does exactly as the before line does, but you get a better stack trace if any error happened
const user = await UserModel.findOne(userCondition).exec(); 

Solution 4 - Javascript

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');

Solution 5 - Javascript

all answers are correct but the easiest way is to use modern async await approach..

async ()=> {
const requiresUser = await User.findByIdAndUpdate(userId,{name:'noname'},{ new:true}).exec()

Solution 6 - Javascript

one way to get data,

find().exec((err,data)=>{

})

other way,

const res=await find()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser439133View Question on Stackoverflow
Solution 1 - JavascriptdanillouzView Answer on Stackoverflow
Solution 2 - JavascriptAnshul KokaView Answer on Stackoverflow
Solution 3 - JavascriptfaridView Answer on Stackoverflow
Solution 4 - JavascriptAlexander MillsView Answer on Stackoverflow
Solution 5 - JavascriptshubhamView Answer on Stackoverflow
Solution 6 - JavascriptNimeth NimdinuView Answer on Stackoverflow