Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Mongoose Model.find() and Model.find().exec() produce the same result. So why bother using Model.find().exec()?

I noticed that Model.find() seems to produce the same outcome as Model.find().exec(). Both seem to retrieve the appropriate record/document as illustrated in the following two snippets of code:

//without exec
export const getUser = async (req, res, next) => {
    try{
        let mongoDocument = await User.find({name: "OrphanAnnie"})
        res.status(200).json(mongoDocument);  
    } catch (err) {
        console.log(err) 
    }
}

//with exec
export const getUser = async (req, res, next) => {
    try{
        let mongoDocument = await User.find({name: "OrphanAnnie"}).exec()
        res.status(200).json(mongoDocument);  
    } catch (err) {
        console.log(err) 
    }
}

Which is the recommended approach? In Mongoose - What does the exec function do? the post suggests that with exec() a Mongoose query can be built without using callback syntax. But since the query seems to work without using exec() at all why bother using it?

like image 599
Luke Avatar asked Nov 29 '25 18:11

Luke


1 Answers

Mongoose have explained the difference of both in promises,

There are two alternatives for using await with queries:

  • await Band.find();
  • await Band.find().exec();

As far as functionality is concerned, these two are equivalent. However, we recommend using .exec() because that gives you better stack traces.

With the example:

const doc = await Band.find({ name: "Guns N' Roses" }); // works

const badId = 'this is not a valid id';
try {
  await Band.find({ _id: badId });
} catch (err) {
  // Without `exec()`, the stack trace does **not** include the
  // calling code. Below is the stack trace:
  //
  // CastError: Cast to ObjectId failed for value "this is not a valid id" at path "_id" for model "band-promises"
  //   at new CastError (/app/node_modules/mongoose/lib/error/cast.js:29:11)
  //   at model.Query.exec (/app/node_modules/mongoose/lib/query.js:4331:21)
  //   at model.Query.Query.then (/app/node_modules/mongoose/lib/query.js:4423:15)
  //   at process._tickCallback (internal/process/next_tick.js:68:7)
  err.stack;
}

try {
  await Band.find({ _id: badId }).exec();
} catch (err) {
  // With `exec()`, the stack trace includes where in your code you
  // called `exec()`. Below is the stack trace:
  //
  // CastError: Cast to ObjectId failed for value "this is not a valid id" at path "_id" for model "band-promises"
  //   at new CastError (/app/node_modules/mongoose/lib/error/cast.js:29:11)
  //   at model.Query.exec (/app/node_modules/mongoose/lib/query.js:4331:21)
  //   at Context.<anonymous> (/app/test/index.test.js:138:42)
  //   at process._tickCallback (internal/process/next_tick.js:68:7)
  err.stack;
}

Other as well: Queries are not promises:

Mongoose queries are not promises. They have a .then() function for co and async/await as a convenience. If you need a fully-fledged promise, use the .exec() function.

const query = Band.find({name: "Guns N' Roses"});
assert.ok(!(query instanceof Promise));

// A query is not a fully-fledged promise, but it does have a `.then()`.
query.then(function (docs) {
  // use docs
});

// `.exec()` gives you a fully-fledged promise
const promise = query.exec();
assert.ok(promise instanceof Promise);

promise.then(function (docs) {
  // use docs
});
like image 82
turivishal Avatar answered Dec 02 '25 19:12

turivishal