node.js - Mongoose.js 唯一验证
问题描述
注意:问题底部有一个编辑:
我可以使用 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.`);
}
}
}
}
解决方案
您的validator
函数只会运行脚本,它不会向 mongoose 传递任何回调或承诺,因此 mongoose 假设验证器返回 true 并继续该过程。根据文档,您应该返回承诺或使用回调。
承诺:
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");
}
});
}
推荐阅读
- function - 结构嵌入、函数输入、多态性
- firebase - 如何使用 Nodemcu 将数据上传到 Firebase?
- ios - 如何在音频停止快速播放后自动更改按钮的背景图像?
- angular - 如果数字大于我分配的某个值,则显示“99+”
- python - 在python3的列表理解中使用if、elif和else
- java - 关于Spring框架中@Lazy注解的问题
- powershell - 将 System.Object 加载到 DataGrid 中
- c++ - 如何将 gmock 函数分配给特定的函数指针?
- javascript - 如何在其他 App Container - React Navigation 中获取参数?
- flutter - ListView 复选框被同时选中