Mongoose:如何防止mongodb在数据库中保存重复的电子邮件记录

时间:2017-05-14 09:36:05

标签: node.js mongodb mongoose

我想在该系列中使密钥电子邮件独一无二,但我无法使其正常工作,这是我的服务器代码。

// Create a schema
var userSchema = new mongoose.Schema({
    email: { type: String, required: true},
    password: String
});

var userModel = mongoose.model("user", userSchema);

router.post('/postuser', (req, res) => {
    console.log('Requested data to server: ' + JSON.stringify(req.body._user));
var user = new userModel({
    email: req.body._user.email,
    password: req.body._user.password
});
// user.isNew = false;
user.save((err, data) => {
    console.log('Analyzing Data...');
    if(data) {
        console.log('Your data has been successfully saved.');
        res.json(data);
}
else {
  console.log('Something went wrong while saving data.');
  console.log(err);
  res.send(err);
}

})
});

注意:我也尝试email: { type: String, required: true, unique: true},但它不起作用,并显示以下错误。

  

名称:' MongoError',

     

消息:' E11000重复密钥错误集合:hutreservationsystem.users

     

index:_Email_1 dup key:{:null}',

     

driver:true,

     

代码:11000,

     

指数:0,

     

errmsg:' E11000重复密钥错误集合:hutreservationsystem.users index:_Email_1 dup key:{:null}',

     

getOperation:[功能],

     

toJSON:[功能],

     

toString:[功能]}

6 个答案:

答案 0 :(得分:4)

Async Custom Validator

var userSchema = new mongoose.Schema({
    password: String,
    email: {
        type: String,
        lowercase: true,
        required: true,
        validate: {
            isAsync: true,
            validator: function(value, isValid) {
                const self = this;
                return self.constructor.findOne({ email: value })
                .exec(function(err, user){
                    if(err){
                        throw err;
                    }
                    else if(user) {
                        if(self.id === user.id) {  // if finding and saving then it's valid even for existing email
                            return isValid(true);
                        }
                        return isValid(false);  
                    }
                    else{
                        return isValid(true);
                    }

                })
            },
            message:  'The email address is already taken!'
        },
    }
});

您可能希望将验证码更改为es6。

答案 1 :(得分:1)

我实现了以下代码以查看是否有任何错误:

var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var express = require('express');
var http = require('http');

var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

var Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');

// Create a schema
var userSchema = new mongoose.Schema({
    email: { type: String, required: true, unique: true},
    password: String
});

var userModel = mongoose.model("user", userSchema);

app.post('/postuser', (req, res) => {
  console.log('Requested data to server: ' + JSON.stringify(req.body._user));
  var user = new userModel({
      email: req.body._user.email,
      password: req.body._user.password
  });
  // user.isNew = false;
  user.save((err, data) => {
      console.log('Analyzing Data...');
      if(data) {
          console.log('Your data has been successfully saved.');
          res.json(data);
      }
      else {
        console.log('Something went wrong while saving data.');
        console.log(err);
        res.send(err);
      }
  })
});

http.createServer(app).listen(3000, function(){
  console.log('Express server listening on port 3000');
});

我确保在我的本地MongoDB数据库中不存在users名称的集合。此外,我使用Postman在http://localhost:3000向我的服务器发送API请求。似乎没有问题,因为我继续添加具有不同电子邮件值的用户。当我输入一个重复值为

的电子邮件时,我只收到以下错误
{
  "code": 11000,
  "index": 0,
  "errmsg": "E11000 duplicate key error collection: test.users index: email_1 dup key: { : \"hot@mail.com\" }",
  "op": {
    "email": "hot@mail.com",
    "password": "1234567",
    "_id": "5919a3428c13271f6f6eab0f",
    "__v": 0
  }
}

这些是我发送的JSON请求:

{"_user": {"email": "hot@mail.com", "password": "1234"}}
{"_user": {"email": "sammy@mail.com", "password": "1234"}}
{"_user": {"email": "tommy@mail.com", "password": "1234"}}
{"_user": {"email": "tommy@mail.ae", "password": "1234567"}}
{"_user": {"email": "hot@mail.com", "password": "1234567"}}

上面提到的错误是在最后一次请求时发回的,因为重复了电子邮件hot@mail.com。 如果您查看链接http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique,您会看到只有在输入的电子邮件不唯一时才会发送E11000错误。此外,您的电子邮件不能是空字符串或不存在,因为它违反了所需的属性。

答案 2 :(得分:1)

使用此工具的简短答案 mongoose-unique-validator

npm install --save mongoose-unique-validator

以及您的模型

var mongoose = require('mongoose')
var uniqueValidator = require('mongoose-unique-validator')
var userSchema = new mongoose.Schema({
    email: { type: String, required: true, unique: true},
    password: String
});

userSchema.plugin(uniqueValidator)
var userModel = mongoose.model("user", userSchema);

就是这样! (通知唯一:是)

现在,您的收藏集中没有电子邮件重复。

奖金! :您可以访问err

.catch(err => console.log(err))

在您的示例中

// user.isNew = false;
user.save((err, data) => {
    console.log('Analyzing Data...');
    if(data) {
        console.log('Your data has been successfully saved.');
        res.json(data);
}
else {
  console.log('Something went wrong while saving data.');
  console.log(err);
  res.send(err);
}

访问错误>> 这样您就可以res.send(err.message)>>“验证失败”

{
    message: 'Validation failed',
    name: 'ValidationError',
    errors: {
        email: {
            message: 'Error, expected `email` to be unique. Value: `example@gmail.com`',
            name: 'ValidatorError',
            kind: 'unique',
            path: 'email',
            value: 'example@gmail.com'
        }
    }
    }

答案 3 :(得分:1)

ES6:

const userSchema = new Schema({
    name: String,
    id: {
        type: String,
        required: true,
        unique: true,
        validate: async (value) => {
            try {
                const result = await userModel.findOne({ id: value })
                if (result) throw new Error("duplicity detected: id :" + value);
            } catch (error) {
                throw new Error(error);
            }
        }
    }
})

const userModel = mongoose.model<Document>('users', userSchema);

ES6(TypeScript):

const userSchema = new Schema({
    name: String,
    id: {
        type: String,
        required: true,
        unique: true,
        validate: async (value: any): Promise<any> => {
            try {
                const result: Document | null = await userModel.findOne({ id: value })
                if (result) throw new Error("duplicity detected: id :" + value);
            } catch (error) {
                throw new Error(error);
            }
        }
    }
})

const userModel: Model<Document, {}> = mongoose.model<Document>('users', userSchema);

答案 4 :(得分:0)

email: {
    type: String,
    trim: true,
    unique: true, // note - this is a unqiue index - not a validation
    validate: {
        validator: function(value) {
            const self = this;
            const errorMsg = 'Email already in use!';
            return new Promise((resolve, reject) => {
                self.constructor.findOne({ email: value })
                    .then(model => model._id ? reject(new Error(errorMsg)) : resolve(true)) // if _id found then email already in use 
                    .catch(err => resolve(true)) // make sure to check for db errors here
            });
        },
    }
},

答案 5 :(得分:0)

在用户架构中,将属性电子邮件设置为唯一(唯一:true)。

var userSchema = new mongoose.Schema({ email: { type: String, required: true,  unique: true}, });