Node.js/Mongoose 上的“VersionError: No matching document found”错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17499089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:57:20  来源:igfitidea点击:

"VersionError: No matching document found" error on Node.js/Mongoose

node.jsmongodbmongoose

提问by toblerpwn

I'm relatively new to Node.js and Mongo/Mongoose, and I'm having a verydifficult time troubleshooting a specific Mongoose error:

我是比较新的Node.js和受蒙戈/猫鼬,和我有一个非常困难的时期排查特定错误猫鼬:

VersionError: No matching document found.

版本错误:找不到匹配的文档。

(Entire error trace/stack at the bottom of this question.)

(此问题底部的整个错误跟踪/堆栈。)

This blog post pretty clearly outline how a VersionError might occur:

这篇博文非常清楚地概述了 VersionError 可能如何发生:

(TL;DR - "Mongoose v3 now adds a schema-configurable version key to each document. This value is atomically incremented whenever a modification to an array potentially changes any array's elements position." If you try to save a document, but the version key no longer matches the object you have retrieved, you get the above VersionError.)

(TL;DR - “Mongoose v3 现在为每个文档添加了一个模式可配置的版本键。只要对数组的修改可能会改变任何数组的元素位置,这个值就会自动递增。”如果您尝试保存文档,但版本键不再与您检索的对象匹配,您将获得上述内容VersionError。)

Core Question:Is there some way to display the offending save()operation? Or which document failed to save? Or anythingat all?! ;)

核心问题:有什么方法可以显示违规save()操作吗?或者哪个文件保存失败?或者什么都没有?!;)

The Challenge:this is a relatively large code base with many arrays, and I am unsure how to begin to troubleshoot the problem. In particular, the error trace/stack does NOT seem to show where the problem exists. See below:

挑战:这是一个包含许多数组的相对较大的代码库,我不确定如何开始解决问题。特别是,错误跟踪/堆栈似乎没有显示问题存在的位置。见下文:

VersionError: No matching document found.
at handleSave (<project_path>/node_modules/mongoose/lib/model.js:121:23)
at exports.tick (<project_path>/node_modules/mongoose/lib/utils.js:408:16)
at null.<anonymous> (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js:484:9)
at g (events.js:192:14)
at EventEmitter.emit (events.js:126:20)
at Server.Base._callHandler (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js:391:25)
at Server.connect.connectionPool.on.server._serverState (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:558:20)
at MongoReply.parseBody (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:131:5)
at Server.connect.connectionPool.on.server._serverState (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:517:22)
at EventEmitter.emit (events.js:96:17)

采纳答案by toblerpwn

Per request, here is an outline of our problem, and how we resolved it:

根据请求,这里是我们问题的概述,以及我们如何解决它:

In our system we created a custom Document locking routine (using redis-lock), wherein the following happened in this precise (incorrect) order:

在我们的系统中,我们创建了一个自定义文档锁定例程(使用 redis-lock),其中以这种精确(不正确)的顺序发生以下情况:

INCORRECT ORDER OF OPERATIONS:

操作顺序不正确:

  1. Client request received
  2. Document locked
  3. Document retrieved
  4. Document edited
  5. Document unlocked
  6. Client request resolved
  7. Document saved
  1. 收到客户请求
  2. 文档已锁定
  3. 检索到的文件
  4. 文件已编辑
  5. 文件解锁
  6. 客户端请求已解决
  7. 文档已保存

Once you see it written out, the problem is obvious: we were saving our Documents outside our Document lock.

一旦你看到它写出来,问题就很明显了:我们将我们的文档保存在我们的文档锁之外。

Let's assume #6 takes 100ms in our system. That is a 100ms window wherein if any other requests grabs that same Document, we're going to have a save conflict (the titled error in this Question is basically a save conflict IMHO).

让我们假设 #6 在我们的系统中需要 100 毫秒。这是一个 100 毫秒的窗口,其中如果任何其他请求获取同一个文档,我们将发生保存冲突(这个问题中的标题错误基本上是保存冲突恕我直言)。

In other words/example: in our system, Request A grabbed Version 1 of Document X, edited it, then unlocked it, but before Request A saved the Document, Request B grabbed Document X and incremented it to Version 2 (read up on Mongo versions for more info about this). Then Request A resolves its Client request and goes to save Document X, but it's trying to save Version 1, and now it sees it has Version 2, and thus the error above.

换句话说/示例:在我们的系统中,请求 A 获取了文档 X 的版本 1,对其进行了编辑,然后将其解锁,但是在请求 A 保存文档之前,请求 B 获取了文档 X 并将其增加到版本 2(阅读 Mongo有关这方面的更多信息的版本)。然后请求 A 解决它的客户端请求并保存文档 X,但它试图保存版本 1,现在它看到它有版本 2,因此出现了上面的错误。

So the fix is easy. Save your Documents inside your lock. (In the above example, move #7 to before #5. See below.)

所以修复很容易。将您的文档保存在您的锁中。(在上面的例子中,将 #7 移到 #5 之前。见下文。)

CORRECT/FIXED ORDER OF OPERATIONS

正确/固定的操作顺序

  1. Client request received
  2. Document locked
  3. Document retrieved
  4. Document edited
  5. Document saved
  6. Document unlocked
  7. Client request resolved
  1. 收到客户请求
  2. 文档已锁定
  3. 检索到的文件
  4. 文件已编辑
  5. 文档已保存
  6. 文件解锁
  7. 客户端请求已解决

(You could make an argument that #6 and #7 should be swapped, but that is outside the scope of Mongo/Mongoose/this question.)

(您可以提出应该交换 #6 和 #7 的论点,但这超出了 Mongo/Mongoose/this question 的范围。)

I am going to leave this question un-answered for a while and see if anyone can shed some light on a better way to isolate the relevant code and troubleshoot this issue. In our case, this was a very systemic problem and VERY challenging to troubleshoot for our skill level at the time.

我将暂时不回答这个问题,看看是否有人可以阐明隔离相关代码和解决此问题的更好方法。在我们的案例中,这是一个非常系统性的问题,并且对我们当时的技能水平进行故障排除非常具有挑战性。

回答by matthijs

It propably points to saving the same document concurrently as robertklep points out.

正如 robertklep 指出的那样,它可能指向同时保存同一个文档。

We had a similar issue running concurrent saves on the same document using async.parallel.

我们在使用 async.parallel 对同一文档运行并发保存时遇到了类似的问题。

回答by Adam Reis

This error can also occur when your process maintains an outdated version of a document in memory and then tries to save it at some point after it has been updated by another process.

当您的进程在内存中维护文档的过时版本,然后在它被另一个进程更新后的某个时刻尝试保存它时,也会发生此错误。

回答by Alex G.

I had the same error when i tried to update a user's reference IDs to an email. The fix was really simple with async / await! Here the code snippet, hope it helps.

当我尝试将用户的参考 ID 更新到电子邮件时,我遇到了同样的错误。使用 async / await 修复非常简单!这是代码片段,希望它有所帮助。

email
    .save()
    .then(() =>
      User.findById(email.from).then(async sender => { // declare function as async
        sender.emails.sent.push(email._id);
        await sender.save(); // wait for save() to complete before proceeding
      }).catch((err) => console.log(err))
    )
    .then(() =>
      User.findById(email.to).then(async receiver => { // same as above
        receiver.emails.received.push(email._id);
        await receiver.save(); // same as above
      }).catch((err) => console.log(err))
    )
    .then(() => res.status(200).json({ message: successMessage }))
    .catch(err => console.log(err));

回答by gianlucaparadise

I had this issue because I was removing an item from an array of a Document using splicefunction.

我遇到这个问题是因为我正在使用splice函数从文档数组中删除一个项目。

I fixed replacing splicefunction with pullfunction from mongoose.

我修复了用mongoose 的函数替换splice函数。pull