Mongoose - exec 函数有什么作用?

IT技术 javascript mongoose
2021-02-01 12:00:29

我遇到了一段 Mongoose 代码,其中包括一个查询 findOne 和一个 exec() 函数。

我以前从未在 Javascript 中见过这种方法吗?它究竟有什么作用?

5个回答

基本上在使用 mongoose 时,可以使用助手检索文档。每个接受查询条件的模型方法都可以通过 acallbackexec方法执行。

callback

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

exec

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

因此,当您不传递回调时,您可以构建查询并最终执行它。

您可以在mongoose 文档中找到更多信息

更新

Promise与 Mongoose 异步操作结合使用时需要注意的是,Mongoose 查询不是Promise。查询确实返回一个thenable,但是如果你需要一个真正的Promise 你应该使用这个exec方法。可以在此处找到更多信息

在更新期间,我注意到我没有明确回答这个问题:

我以前从未在 Javascript 中见过这种方法吗?它究竟有什么作用?

好吧,它不是原生 JavaScript 方法,而是 Mongoose API 的一部分。

如果我设置了 mongoose.Promise = require('bluebird'),我还需要使用 .exec() 吗?谢谢。
2021-03-27 12:00:29
@wayofthefuture 我发现文档对此事真的很困惑,但我相信您仍然需要调用该exec方法。这至少是他们在文档中所做的。为确保您可以使用Model.find() instanceof require('bluebird'). 希望这可以帮助。
2021-03-27 12:00:29
exec 也返回一个promise,如果没有回调传递,这很方便我必须说
2021-03-31 12:00:29
然后还有其他操作的问题,例如 delete 和 insertMany ... 在这些情况下是否需要 exec() ?删除将不得不在引擎盖下使用某种查询......
2021-04-09 12:00:29
它可能会救人如果您认为 Model.update() 会完成它的工作并且不要等待一些不那么重要的数据更新并向 API 返回响应;您的更新不会执行。您需要Model.update().exec()确保它会执行。然后你就可以响应api而无需等待更新。
2021-04-10 12:00:29

丹尼尔很好地回答了这个问题。要详细说明构建和执行查询的方法的详尽列表,请查看以下用例:

查询构建

Mongoose 不会执行查询,直到thenexec已被调用。这在构建复杂查询时非常有用。一些示例可以包括使用populateaggregate函数。

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

通过回调执行

尽管由于其嵌套性质而被许多人不喜欢,但可以通过提供可选的回调来执行查询。

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

然后 API 作为 Promises/A+

Mongoose 查询确实提供了一个then功能。这不要与常规Promise混淆。简而言之,Promises/A+ 规范需要一个then函数来工作,就像我们习惯于使用 Promise 一样。

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

执行函数

来自mongoose文档 If you need a fully-fledged promise, use the .exec() function.

User.find({name: 'John'}).exec(); // Will execute returning a promise
你能用 .exec() 添加一个完整的例子吗?@AnshulKoka 是 .exec() 自动使查询异步还是我应该添加 async/await
2021-03-13 12:00:29
使查询异步将需要 async/await,所以我不确定我是否理解这个问题。只需在我的示例前加上 await 即可获得完整示例。
2021-03-13 12:00:29
如上所述,您也可以then在查询上使用以返回Promise。这与exec. 我发现这很方便的用例是在使用类似Promise.all. 不确定返回的Promise是否exec在这种情况下有效。
2021-03-17 12:00:29
文档没有明确提及它,但示例显示 User.save() 也返回了一个Promise。除了 exec() 和 save() 模型上的任何其他mongoose方法都返回一个Promise,还是只是这两个?
2021-03-21 12:00:29
请参阅此处的说明:stackoverflow.com/a/46457247/3904109
2021-03-22 12:00:29

我从不使用exec()函数在模型上完成 CRUD(创建、读取、更新、删除)。当我想在模型上使用 CRUD 时,我会像这样使用它:

const user = await UserModel.findOne(userCondition);

它总是能胜任。所以我想知道“有什么exec()用”?当我在mongoose文档中搜索时,我在这里找到了答案

你应该在等待中使用 exec() 吗?

这是故事。
您有两种方法可以对模型执行查询。使用callback或使用exec()功能。“但是”你也可以用awaitexec()函数返回一个Promise,您可以将它与“异步”模型一起使用then()async/await执行查询。所以问题是“如果我可以使用user = await UserModel.find()并且它可以正常工作,那么我为什么要使用exec()函数?”。您可以在文档中找到的答案是:

使用awaitexec()使用它有两个区别

  • 作为视图的官能度点,存在使用之间没有差异awaitexec()或没有它。就在您调用不带exec()or的查询时callback,它返回一个thenable类似于 promise 但它不是 promise。(您可以在此处找到区别)。但是当您exec()用来运行查询时,您会得到一个Promise作为响应。
// 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(); 
  • 另一个区别是,如果您使用awaitwith ,如果您exec()在执行查询时发现任何错误,您将获得更好的“堆栈跟踪”。所以:

    这两行,做同样的事情:
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(); 
清晰明了的解释,谢谢。
2021-03-16 12:00:29
非常重要的区别!在测试我的查询时,我注意到当我故意扭曲 url 中 _id 字段的格式以测试错误时,try/catch 没有选择错误并且我的模型发出了已弃用的警告,这Promise返回错误没有被抓到以后不会再被收容。
2021-04-07 12:00:29

exec()如果没有提供回调,将返回一个Promise。所以下面的模式非常方便和通用——它可以很好地处理回调或Promise:

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

}

我建议在 Mongoose 中使用 Bluebird Promise,为此,请使用以下调用:

const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
为什么我们需要蓝鸟?当我们有 exec()
2021-03-16 12:00:29

所有答案都是正确的,但最简单的方法是使用现代异步等待方法..

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