2

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?

turivishal
  • 34,368
  • 7
  • 36
  • 59
Luke
  • 2,751
  • 1
  • 17
  • 20
  • Only very imperfectly. That post suggests that exec() allows you to execute a Mongoose query without a callback. But it seems like one can execute the Mongoose query even without exec(). – Luke Apr 04 '21 at 18:10
  • BTW, one can also execute the query this way: export const getUser = (req, res, next) => { User.find({ name: "OrphanAnnie" }) .then(function (user) { return res.json(user); }) .catch(function (err) { return res.json(err); }); } But even while this works, it doesn't clarify what the exec does when using the await syntax approach.... – Luke Apr 04 '21 at 18:11

1 Answers1

2

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
});
turivishal
  • 34,368
  • 7
  • 36
  • 59
  • 1
    Awesome! This clarifies things. Thank you very much. A big thumbs up to you! And nice sleuthing in the Mongoose docs. If you simply search on "Exec" as i did in the Mongoose search field the page you cite AFAIK does not appear. Is that a problem with the docs? Or are you using some other logic to find that info? – Luke Apr 04 '21 at 19:23