【问题标题】:Mongoose.js Unique ValidationMongoose.js 唯一验证
【发布时间】:2019-09-24 02:27:58
【问题描述】:

注意:问题底部有一个编辑:

我可以使用自定义验证器或 Mongoose.js 模型文件中的预挂钩来检查数据库的唯一性吗?我知道我可以在控制器中检查它,但我宁愿将它与其他验证器一起放入模型文件中,以保持一致性。

我也知道有一个名为 mongoose-unique-validator 的 npm 包可以执行此操作,但我不喜欢安装一个库来执行应该是一到五行代码的操作。

Mongoose 还有一个“唯一”属性,如果项目不是唯一的,该属性将引发错误。但他们的文件清楚地表明这不是验证器。并且它抛出的错误不会与验证错误相同。

这里是模型文件的相关部分。这将检查数据库,如果没有 dup 则创建文章,但如果有 dup 则会引发错误,但不会引发我想要的验证错误。如果我只是在有 dup 的情况下返回 false,它只会忽略验证并创建重复的文章。这无疑与 Promises/Async 有关。以下是相关的 Mongoose 文档https://mongoosejs.com/docs/validation.html#async-custom-validators。他们谈论了独特的属性如何不是验证器https://mongoosejs.com/docs/faq.html

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const articleSchema = new Schema({
  title: {
    type: String,
    required: [true, "Title is required"],
    // unique: true, 
    // isAsync: true,
    validate: {
      validator: function(value) {
        this.constructor.findOne({title: value}, (err, article) => {
          if (err || !article) { 
            return true;
          } else {
            // return false;
            throw new Error('Duplicate');
          }
        });
      },
      message: (props) => `Title "${props.value}" is already in use.`
    },
  },
  content: { type: String, required: true }
});

编辑:我想通了,但它只在创建新文章时有效,在更新时无效。所以这个问题仍然悬而未决,但重点是如何让它在更新上工作。在更新时,Mongoose 不会像在创建时那样将“this”视为文档对象。相反,“this”是请求对象,“this.constructor.findOne()”会抛出错误“this.constructor.findOne is not a function”。这是修改后的验证器:

  title: {
    type: String,
    required: [true, "Title is required"],
    isAsync: true,
    validate: {
      validator: async function(value) {
        const article = await this.constructor.findOne({title: value});
        if (article) {
          throw new Error(`${value} is already in use.`);
        }
      }
    }
  }

【问题讨论】:

  • 你可以检查stackoverflow.com/questions/11872556/…。这是相似的。或者你可以使用npmjs.com/package/mongoose-unique-validator
  • 感谢您指出这个问题。我没见过。但它似乎没有给我想要的东西。实际上我想出了如何为一篇新文章做这件事,但它在更新时不起作用。因此,我将使用该新信息编辑我的问题。
  • mongoosejs.com/docs/validation.html#update-validators你试过打开验证器选项吗?
  • 是的,它已开启。其他验证器,如必需的,用于更新。它实际上是在尝试在更新时运行自定义验证器,但由于“this”问题,它无法引用该对象。除非我将条件包装在它周围以仅在创建时运行,否则上述内容会在更新时引发错误。

标签: node.js validation mongoose


【解决方案1】:

您的validator 函数只会运行脚本,它不会向 mongoose 传递任何回调或承诺,因此 mongoose 假设验证器返回 true 并继续该过程。 根据文档,你应该返回promise或者使用callback。

承诺:

validator: function(value) {
    var here = this;
    return new Promise(function(resolve, reject) {
        here.constructor.findOne({title: value}, (err, article) => {
        if (err || !article) { 
          resolve(true);
        } else {
          resolve(false);
        }
      });
    })
}

回调:(需要设置isAsync: true

validator: function(value, cb) {
      this.constructor.findOne({title: value}, (err, article) => {
        if (err || !article) { 
          cb(true);
        } else {
          cb(false, "Content is used");
        }
     });
}

【讨论】:

  • 不幸的是,这些都不起作用。即使有重复,第一个创建的文章也是如此。第二个抛出回调不是函数的错误。我在尝试之前修复了您答案中的拼写错误,但仍然没有成功。但实际上我确实想通了,只是发现了一个新问题。 This.constructor 仅适用于不更新的创建操作。结果 Mongoose 以不同的方式处理更新,所以我仍然不在家。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-17
  • 2018-07-29
  • 1970-01-01
  • 2018-04-30
  • 2017-10-11
  • 1970-01-01
  • 2021-09-11
相关资源
最近更新 更多