Mongoose不能通过文档阵列编辑和版本控制进行扩展吗?

Chr*_*ter 4 javascript mongoose mongodb node.js express

我正在使用Node.js和MongoDB/Mongoose开发Web应用程序.我们最常用的Model,Record,有许多子文档数组.例如,其中一些包括"评论","预订"和"订阅者".

在客户端应用程序中,每当用户点击"删除"按钮时,它就会触发针对该特定注释的删除路由的AJAX请求.我遇到的问题是,当许多AJAX调用同时进入时,Mongoose在某些(但不是全部)调用中失败并显示"Document not found"错误.

这种情况只发生在一次快速拨号和多次拨号时.我认为这是由于Mongoose中的版本导致文档冲突.我们目前的删除流程是:

  1. 使用获取文档 Record.findById()
  2. 从相应的数组中删除子文档(例如,使用comment.remove())
  3. 呼叫 record.save()

我找到了一个解决方案,我可以手动更新集合Record.findByIdAndUpdate,然后使用$pull运算符.但是,这意味着我们不能使用任何mongoose的中间件并完全松开版本控制.我越是想到它,我越发明这种情况会发生,我将不得不使用Mongoose的包装函数,如findByIdAndUpdate或findAndRemove.我能想到的唯一其他解决方案是将删除尝试放入while循环并希望它能够正常工作,这似乎是一个非常糟糕的修复.

使用Mongoose包装器并没有真正解决我的问题,因为它根本不允许我使用任何类型的中间件或钩子,这基本上是使用Mongoose的巨大好处之一.

这是否意味着Mongoose对于快速编辑的任何东西都是无用的,我可能只使用本机MongoDB驱动程序?我误解了猫鼬的局限吗?我怎么能解决这个问题?

Joh*_*yHK 6

Mongoose的版本化文档数组编辑不可扩展,原因很简单,因为它不是原子操作.因此,您拥有的阵列编辑活动越多,两次编辑碰撞的可能性就越大,您将遇到代码重试/恢复的开销.

对于可扩展的文件数组操作,你必须使用update与原子阵列更新运营商:$pull[All],$push[All],$pop,$addToSet,和$.当然,您也可以将这些运算符与findAndModify基于原子的方法一起使用findByIdAndUpdate,findOneAndUpdate如果您还需要原始文档或生成的文档.

正如您所提到的,使用update而不是findOne+ 的重大缺点save是您的Mongoose中间件和验证都不会在执行期间执行update.但是如果你想要一个可扩展的系统,我没有看到你有任何选择.我更倾向于为更新案例手动复制一些中间件和验证逻辑,而不是使用Mongoose的版本化文档数组编辑的可扩展性惩罚.嘿,至少你仍然可以获得Mongoose基于模式的类型转换更新的好处!