如何检查更新过程中数据库中是否已经存在数据(Mongoose And Express)

在将编辑的数据保存在mongoose中之前如何进行validation?

例如,如果sample.name已经存在于数据库中,那么用户将会收到一些类似的错误,下面是我的代码

 //Post: /sample/edit app.post(uri + '/edit', function (req, res, next) { Sample.findById(req.param('sid'), function (err, sample) { if (err) { return next(new Error(err)); } if (!sample) { return next(new Error('Invalid reference to sample information')); } // basic info sample.name = req.body.supplier.name; sample.tin = req.body.supplier.tin; // contact info sample.contact.email = req.body.supplier.contact.email; sample.contact.mobile = req.body.supplier.contact.mobile; sample.contact.landline = req.body.supplier.contact.landline; sample.contact.fax = req.body.supplier.contact.fax; // address info sample.address.street = req.body.supplier.address.street; sample.address.city = req.body.supplier.address.city; sample.address.state = req.body.supplier.address.state; sample.address.country = req.body.supplier.address.country; sample.address.zip = req.body.supplier.address.zip; sample.save(function (err) { if (err) { return next(new Error(err)); } res.redirect(uri + '/view/' + sample._id); }); }); }); 

通常你可以使用mongoosevalidation,但是因为你需要一个asynchronous的结果(对现有名称的数据库查询)和validation器不支持承诺(从我可以告诉),您将需要创build自己的函数并传递callback。 这里是一个例子:

 var mongoose = require('mongoose'), Schema = mongoose.Schema, ObjectId = Schema.ObjectId; mongoose.connect('mongodb://localhost/testDB'); var UserSchema = new Schema({ name: {type:String} }); var UserModel = mongoose.model('UserModel',UserSchema); function updateUser(user,cb){ UserModel.find({name : user.name}, function (err, docs) { if (docs.length){ cb('Name exists already',null); }else{ user.save(function(err){ cb(err,user); }); } }); } UserModel.findById(req.param('sid'),function(err,existingUser){ if (!err && existingUser){ existingUser.name = 'Kevin'; updateUser(existingUser,function(err2,user){ if (err2 || !user){ console.log('error updated user: ',err2); }else{ console.log('user updated: ',user); } }); } }); 

更新:一个更好的方法

预钩似乎是一个更自然的地方停止保存:

 UserSchema.pre('save', function (next) { var self = this; UserModel.find({name : self.name}, function (err, docs) { if (!docs.length){ next(); }else{ console.log('user exists: ',self.name); next(new Error("User exists!")); } }); }) ; 

更新2:asynchronous自定义validation器

它看起来像mongoose现在支持asynchronous自定义validation器,所以这可能是自然的解决scheme:

  var userSchema = new Schema({ name: { type: String, validate: { validator: function(v, cb) { User.find({name: v}, function(err,docs){ cb(docs.length == 0); }); }, message: 'User already exists!' } } }); 

继续使用@nfreeze示例的另一种方法是validation方法:

 UserModel.schema.path('name').validate(function (value, res) { UserModel.findOne({name: value}, 'id', function(err, user) { if (err) return res(err); if (user) return res(false); res(true); }); }, 'already exists'); 

这是用较less的代码来完成这个的另一种方法。

更新3:asynchronous模型类静态

与选项2类似,这允许您创build直接链接到模式的函数,但使用模型从相同的文件调用。

model.js

  userSchema.statics.updateUser = function(user, cb) { UserModel.find({name : user.name}).exec(function(err, docs) { if (docs.length){ cb('Name exists already', null); } else { user.save(function(err) { cb(err,user); } } }); } 

从文件中调用

 var User = require('./path/to/model'); User.updateUser(user.name, function(err, user) { if(err) { var error = new Error('Already exists!'); error.status = 401; return next(error); } }); 

如果你正在寻找一个唯一的索引,那么使用UserModel.count实际上可能比UserModel.findOne更好,因为它返回整个文档(即做一个读取),而不是只返回一个int。