2

I am working on a NodeJS application where, express is the framework & MongoDB is the database. I am using mongoose plugin for it.

I have a parent model. I have added unique: true to field "mobile". But whenever I add same mobile number, uniqueness validation fails. Nothing happens rather duplicate document gets saved. The required validation works fine but unique validation does not work only in this particular model.

Below is the model parentModel.js

var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
mongoose.set('useCreateIndex', true);
var Schema   = mongoose.Schema;

var parentSchema = new Schema({
    'name' : {
    type: String,
    required: true
  },
    'mobile' : {
    type: Number,
    unique: true,
    required: true
  },
    'password' : {
    type: String,
    select: false
  },
    'address' : {
    type: String,
    required: true
  },
    'notifications' : [{
        'title': {
        type: String,
        required: true
      },
      'body': {
        type: String,
        required: true
      },
      'path': {
        type: String,
        required: true
      },
    }],
    'activities' : [{
        'title': {
        type: String,
        required: true
      },
      'body': {
        type: String,
        required: true
      },
      'date': {
        type: Date,
        required: true
      }
    }],
    'isVerified' : {
        type: Boolean,
    default: false
    }
},
{
    timestamps: true
});

parentSchema.pre('save', function (next) {
  var parent = this;
  if (this.isNew) {
    var randomstring = Math.random().toString(36).slice(-8);
    bcrypt.genSalt(10, function (err, salt) {
      if (err) {
        return next(err);
      }
      bcrypt.hash(randomstring, salt, null, function (err, hash) {
        if (err) {
          return next(err);
        }
        parent.password = hash;
        next();
      });
    });
  } 
  else if (this.isModified('password')) {
    bcrypt.genSalt(10, function (err, salt) {
      if (err) {
        return next(err);
      }
      bcrypt.hash(parent.password, salt, null, function (err, hash) {
        if (err) {
          return next(err);
        }
        parent.password = hash;
        next();
      });
    });
  }
  else {
    return next();
  }
});

parentSchema.methods.comparePassword = function (passw, cb) {
  console.log(passw)
    bcrypt.compare(passw, this.password, function (err, isMatch) {
        if (err) {
            return cb(err);
        }
        cb(null, isMatch);
    });
};

module.exports = mongoose.model('parent', parentSchema);

Below is the controller parentController.js

create: function (req, res) {
        var parent = new parentModel({
            name : req.body.name,
            mobile : req.body.mobile,
            address : req.body.address

        });

        parent.save(function (err, parent) {
            if (err) {
                return res.status(500).json({
                    message: 'Error when creating parent',
                    error: err
                });
            }
            return res.status(201).json(parent);
        });
    }
halfer
  • 19,824
  • 17
  • 99
  • 186
Bibek Das
  • 35
  • 10
  • Does this answer your question? [Mongoose Not Creating Indexes](https://stackoverflow.com/questions/12452865/mongoose-not-creating-indexes) – SuleymanSah Dec 21 '19 at 11:32
  • No, I have tried using index: true. Nothing happens. The required validation works fine but unique validation does not work in this particular model. – Bibek Das Dec 21 '19 at 11:46

1 Answers1

1

Use the following code to check if mongoose could able to create index:


const Parent = mongoose.model('parent', parentSchema);

Parent.on('index', function(err) { 

  if (err) {
    console.log("Could not create index: ", err)
  } else {
    console.log("Index created")
  }

});

module.exports = Parent;

If it gives error, you can create index on MongoDB side.

db.parents.createIndex( { "mobile": 1 }, { unique: true } );

In the docs it says:

In a production environment, you should create your indexes using the MongoDB shell rather than relying on mongoose to do it for you. The unique option for schemas is convenient for development and documentation, but mongoose is not an index management solution.

SuleymanSah
  • 17,153
  • 5
  • 33
  • 54
  • Thank you so much. The index was not present. I just have one question more, what if we use index: true and unique: true together ? My current problem was solved as soon as i added index:true and dropped the collection. Will i use db.parents.createIndex( { "mobile": 1 }, { unique: true } ); or index:true ? – Bibek Das Dec 21 '19 at 12:30
  • @BibekDas I guess like this `db.parents.createIndex( { "mobile": 1 }, { unique: true } )` , in the official docs of mongodb, they use like this. https://docs.mongodb.com/manual/core/index-unique/#create-a-unique-index – SuleymanSah Dec 21 '19 at 12:32
  • Sure. I might be wrong. But may be adding index: true to the model's key is the mongoose way of doing this exact thing, db.parents.createIndex( { "mobile": 1 }, { unique: true } ). Not sure though. Anyways thank you so much for your help. Much appreciated. – Bibek Das Dec 21 '19 at 13:59