Javascript 我在这个 Mongoose 独特的预保存验证中做错了什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11872556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:28:18  来源:igfitidea点击:

What am I doing wrong in this Mongoose unique pre-save validation?

javascriptnode.jsmongoose

提问by Geo

I'm trying to create a User model, that has an unique username. Here's the code for it:

我正在尝试创建一个用户模型,它具有唯一的用户名。这是它的代码:

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);

I was also testing to see if the uniqueness works:

我也在测试唯一性是否有效:

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();
});

Problem is, it doesn't. Each time I run the code, I get a new object created. I am aware that there are probably other ways of ensuring uniqueness, but I'd like to do it in this way. Shouldn't I be calling doneafter I handle the result of the findOnemethod? Am I calling nextwrong?

问题是,它没有。每次运行代码时,都会创建一个新对象。我知道可能还有其他方法可以确保唯一性,但我想这样做。done处理完findOne方法的结果后,我不应该调用吗?我叫next错了吗?

回答by rdrey

http://mongoosejs.com/docs/api.html#schematype_SchemaType-uniqueis the way to go. It uses actual MongoDb indexes to make sure that your field is unique. No need for .premiddleware.

http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique是要走的路。它使用实际的 MongoDb 索引来确保您的字段是唯一的。不需要.pre中间件。

Enjoy!

享受!

回答by JohnnyHK

To use parallel middleware(with nextand doneparameters), you need to pass trueas the second parameter.

要使用并行中间件(带nextdone参数),您需要true作为第二个参数传递。

Beyond that, there are two possibilities:

除此之外,还有两种可能:

Your self.invalidatecall should be referencing "username"instead of "user". If that doesn't fix it, you can fail things explicitly by passing an Error object to doneif you want to abort the save operation:

您的self.invalidate电话应该是引用"username"而不是"user". 如果这不能解决它,done如果您想中止保存操作,您可以通过将 Error 对象传递给显式失败:

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();
});

回答by thomas-peter

There's a really good plugin for mongoose that's really easy to install and use. The documentation is excellent and it worked for me first time.

有一个非常好的 mongoose 插件,非常易于安装和使用。文档非常好,第一次对我有用。

But there is an issue with re-saving.

但是重新保存存在问题。

https://npmjs.org/package/mongoose-unique-validator

https://npmjs.org/package/mongoose-unique-validator

回答by furf

Have you considered using an asynchronous validator to catch the error?

您是否考虑过使用异步验证器来捕获错误?

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');