Что я делаю неправильно в этой уникальной предварительной проверке Mongoose?
Я пытаюсь создать модель User, которая имеет уникальное имя пользователя. Вот код для него:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String,
password: String,
});
UserSchema.virtual("password_confirmation").get(function() {
return this.pw_conf;
}).set(function(value) {
this.pw_conf = value;
});
UserSchema.path("username").required(true);
UserSchema.path("password").required(true);
UserSchema.pre("save",function(next, done) {
var self = this;
mongoose.models["User"].findOne({username : self.username},function(err, user) {
if(user) {
self.invalidate("user","username must be unique");
}
done();
});
next();
});
UserSchema.pre("save",function(next) {
if(this.pw_conf !== this.password) {
next(new Error("Must specify the password confirmation"));
}
else {
next();
}
});
module.exports = mongoose.model("User",UserSchema);
Я также тестировал, работает ли уникальность:
var User = require("./users"),
mongoose = require("mongoose");
var u = new User();
mongoose.connect('mongodb://localhost/my_database');
u.username = "me";
u.password = "password";
u.password_confirmation = "password";
u.save(function(err) {
if(err) {
console.log(err);
}
mongoose.disconnect();
});
Проблема в том, что нет. Каждый раз, когда я запускаю код, я создаю новый объект. Я знаю, что есть, вероятно, другие способы обеспечения уникальности, но я хотел бы сделать это таким образом. Не следует ли мне называть done
после обработки результата метода findOne
? Я вызываю next
неправильно?
Ответы
Ответ 1
Чтобы использовать параллельное промежуточное ПО (с параметрами next
и done
), вам необходимо передать true
в качестве второго параметра.
Кроме того, существует две возможности:
Ваш вызов self.invalidate
должен ссылаться на "username"
вместо "user"
. Если это не исправить, вы можете явно пропустить ситуацию, передав объект Error в done
, если вы хотите прервать операцию сохранения:
UserSchema.pre("save", true, function(next, done) {
var self = this;
mongoose.models["User"].findOne({username: self.username}, function(err, user) {
if(err) {
done(err);
} else if(user) {
self.invalidate("username", "username must be unique");
done(new Error("username must be unique"));
} else {
done();
}
});
next();
});
Ответ 2
http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique - это путь. Он использует фактические индексы MongoDb, чтобы убедиться, что ваше поле уникально. Нет необходимости в промежуточном программном обеспечении .pre
.
Наслаждайтесь!
Ответ 3
Там действительно хороший плагин для mongoose, который очень прост в установке и использовании. Документация отличная, и она работала для меня в первый раз.
Но проблема с повторной сохранностью.
https://npmjs.org/package/mongoose-unique-validator
Ответ 4
Рассматривали ли вы использование асинхронного валидатора для обнаружения ошибки?
UserSchema.path('username').validate(function (value, done) {
User.count({ username: value }, function (error, count) {
// Return false if an error is thrown or count > 0
done(!(error || count));
});
}, 'unique');