我对Node比较陌生.js和Mongo/Mongoose,我在排除特定Mongoose错误时遇到了very个困难:

VersionError: No matching document found.

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

这篇博客文章非常清楚地概述了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 100.)

Core Question:.有没有什么方法可以显示违规的save()操作?或者哪个文档未能保存?或者是anything个?!;)

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

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)

推荐答案

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

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

INCORRECT ORDER OF OPERATIONS:

  1. 收到客户请求
  2. 文件已锁定
  3. 检索到的文档
  4. 文件编辑
  5. 文件解锁
  6. 客户端请求已解决
  7. Document saved

一旦看到它被写出来,问题就显而易见了:我们在文档锁之外保存文档.

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

换句话说/例如:在我们的系统中,请求抓取文档X的版本1,编辑它,然后解锁它,但在请求A保存文档之前,请求B抓取文档X并将其增加到版本2(阅读Mongo版本了解更多信息).然后请求A解析其客户机请求并保存文档X,但它正试图保存版本1,现在它看到它有版本2,因此出现上述错误.

所以解决方法很简单.将文件保存在锁中.(在上例中,将#7移动到#5之前.请参见下文.)

CORRECT/FIXED ORDER OF OPERATIONS

  1. 收到客户请求
  2. 文件已锁定
  3. 检索到的文档
  4. 文件编辑
  5. Document saved
  6. 文件解锁
  7. 客户端请求已解决

(你可以提出一个论点,认为#6和#7应该互换,但这超出了Mongo/Mongoose/这个问题的范围.)

我将暂时不回答这个问题,看看是否有人能提供更好的方法来隔离相关代码并解决这个问题.在我们的 case 中,这是一个非常系统性的问题,对于我们当时的技能水平来说,排除故障非常具有挑战性.

Mongodb相关问答推荐

使用查询参数过滤MongoDB Go驱动程序时出现问题

数组中字符串的Mongo查询集合和推送到新数组嵌套对象

无法配置数据源:未指定url属性,无法为 MongoDb 配置嵌入数据源

MongoDb聚合查询问题

从 MongoDB 中的聚合结果中获取不同的值

在mongodb中,如何使用聚合来获取字段之间的对应关系

_id 和 $oid 的区别; mongo 数据库中的 $date 和 IsoDate

如何根据_id删除文档?

使用 AngularJs 和 MongoDB/Mongoose

Mongo 可尾游标与 Redis 发布/订阅

mongodb上不区分大小写的查询

mongodb 模式设计命名约定

Spring Mongo 条件查询两次相同的字段

如何返回 MongoDB 中文档的 ObjectId 或 _id?和错误$in 需要一个数组

MongoDB聚合排序不起作用

MongoDB:自动生成的 ID 为零

Mongoose.pre('save') 不会触发

Java Mongodb 正则表达式查询

Mongoid 不在查询中

MongoDB Compass:select distinct field values