mongoose在pre(';update';)上更改更新对验证无效

mongoose在pre(';update';)上更改更新对验证无效,mongoose,mongoose-schema,Mongoose,Mongoose Schema,下面的代码包含模式和用于操作模式的name属性的pre('update')中间件。实际上,我只想在name属性中添加一个后缀,如果该值已经存在于Item集合中 const ItemSchema = mongoose.Schema({ ... name : {type : String, required : true, unique : true, trim : true}, ... }) ItemSchema.pre("update", async function() {

下面的代码包含模式和用于操作模式的name属性的pre('update')中间件。实际上,我只想在name属性中添加一个后缀,如果该值已经存在于Item集合中

const ItemSchema = mongoose.Schema({
  ...
  name : {type : String, required : true, unique : true, trim : true},
  ...
})

ItemSchema.pre("update", async function() {
  let name = this.getUpdate().$set.name;
  if (!name) return Promise.resolve();
  let count = await ItemModel.find({name}).count().exec();
  if(count>0) name = name + "_SOME_SUFFIX_BY_SOME_LOGIC";
  this.getUpdate().$set.name = name;
});

ItemSchema.plugin(require('mongoose-unique-validator'));

const ItemModel = mongoose.model('Item', ItemSchema);
module.exports = ItemModel;
然后,当我尝试更新/修补name属性时,计数似乎正确地得到了数字1,并通过后缀更新了名称。之后,我使用正确操作的名称正确更新更新对象中的名称(因此,带有后缀的名称肯定不存在于集合中)

但现在,当我尝试更新时,出现以下错误:

验证失败:名称:错误,预期
name
是唯一的。价值: `[名称]\u一些\u后缀\u由\u一些\u逻辑'

所以它告诉我,新的后缀名已经存在于数据库中,即使它不存在

(我已经在数据库中查找了后缀名,但我可以保证它不在那里,因为我在测试集合上运行这个,所以还没有太多条目)


节点版本:8.1.1 mongoose版本:5.1.3系统:ubuntu 16.04

我实际发现,mongoose唯一验证器是这里的问题。我在一期猫鼬杂志上找到了一条评论,描述了原因

因为mongoose唯一验证器依赖于异步操作,比如 .count()要验证数据库中是否存在文档,请 可能会同时执行两个.count()调用, 两者都返回0,然后都插入MongoDB。你需要这样做 一些锁定操作,使其在一般情况下正常工作

解决这个问题的唯一方法是只使用一个进程和一个集合 您的mongodb连接池大小为1,但这限制了 您可以运行的应用服务器,并且只有在mongodb保留的情况下才能运行 它的遗留行为是在每个连接的基础上阻塞操作