【发布时间】: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.`);
}
}
}
}
【问题讨论】:
-
感谢您指出这个问题。我没见过。但它似乎没有给我想要的东西。实际上我想出了如何为一篇新文章做这件事,但它在更新时不起作用。因此,我将使用该新信息编辑我的问题。
-
是的,它已开启。其他验证器,如必需的,用于更新。它实际上是在尝试在更新时运行自定义验证器,但由于“this”问题,它无法引用该对象。除非我将条件包装在它周围以仅在创建时运行,否则上述内容会在更新时引发错误。
标签: node.js validation mongoose