Mongoose & unique field
Asked Answered
H

2

67

I have the following schema with mongoose:

var SimSchema = new Schema({
    msisdn     : { type : String , unique : true, required : true },
    imsi       : { type : String , unique : true, required : true },
    status     : { type : Boolean, default: true},
    signal     : { type : Number },
    probe_name : { type:  String , required : true }
});

I have uniqueoption for the msisdn and imsi.

In some cases this condition is well respected. For the following mocha test:

"use strict";

var app      = require('../../app');
var http     = require('http');
var request  = require('supertest');
var mongoose = require('mongoose');
var should   = require('should');



describe('[ Sim controller ] ', function(){
  before(function(done) {
    app.set_env('test');
    this.server = app.start(function() {
      mongoose.connection.db.dropDatabase(function() {
        done();
      })
    });
  });


  beforeEach(function(done){
    done();
  });


  it('Sim with good parameters should be created in the database', function(done){
    var newSim = {
      msisdn:     '1234',
      imsi:       '007',
      probe_name: 'BOUCHON_1'
    };

    request(this.server)
      .post('/sims')
      .set('Content-Type', 'application/json')
      .send(newSim)
      .expect(200).end(function(err, res) {
        if (err) return done(err);
        res.body.should.have.property('imsi');
        res.body.should.have.property('probe_name');
        res.body.should.have.property('msisdn');
        setTimeout(function() {
          done();
        }, 1000);
      });
  });


  it('Sim imsi/msisdn is unique in the database', function(done){
    var newSim = {
      msisdn:     '1234',
      imsi:       '007',
      probe_name: 'BOUCHON_1'
    };

    request(this.server)
      .post('/sims')
      .set('Content-Type', 'application/json')
      .send(newSim)
      .expect(200).end(function(err, res) {
        if (err) return done(err);
        res.body.should.have.property('error').equal('Duplicate Item');
        done();
      });
  });


  after(function(done) {
    app.stop(done);
  });
});

It's working fine if I run it directly:

julio$ mocha test/controllers/ctrl_sim.js 

But If I run it thanks to the recessive option it failed:

  1) [ Sim controller ]  Sim imsi/msisdn is unique in the database:
     Uncaught AssertionError: expected { __v: 0,
  imsi: '007',
  msisdn: '1234',
  probe_name: 'BOUCHON_1',
  _id: '530a2b7f52273aa90783baf0',
  status: true } to have property 'error'

I read on stack that sometimes the unique condition is not well respected as the index is not refreshed. Do you think this is my case? In fact, I delete the database for each mocha test suite. Maybe mongo doesn't have the time to recreate all the indexes each time.

Any idea?

Heliotropism answered 23/2, 2014 at 17:25 Comment(0)
F
100

Use dropDups to ensure dropping duplicate records in your schemas like;

var SimSchema = new Schema({
    msisdn     : { type : String , unique : true, required : true, dropDups: true },
    imsi       : { type : String , unique : true, required : true, dropDups: true },
    status     : { type : Boolean, default: true},
    signal     : { type : Number },
    probe_name : { type:  String , required : true }
});

And before running your tests, restart mongodb

Fifi answered 24/2, 2014 at 15:17 Comment(12)
I am not able to understand the use of dropDups. can you please elaborate?Refugiorefulgence
@VikasBansal I guess if you set dropDups to true, the mongodb will drop previously created duplicates if there are anyMarr
@HasaanAli Not quite - dropDups means that MongoDB will "drop" any queries which try to create a record with a schema value that already exists in the database. For ex: if you already have a record with name:bob and you try to insert another record with name:bob then this insertion will fail due to dropDups.Criminology
I can't seem to find the dropDups option documentation in mongoose, could anyone post the link to it?Workhouse
@WilliamHu AFAIK any field can be set to unique and not necessarily index only. Please correct me if I am mistaken.Knockwurst
@Knockwurst I think you are not correct. I think unique index mentioned here docs.mongodb.com/manual/core/index-unique Also you could try if it works : )Amenity
@WilliamHu Thanks a bunch for marking that our, sir. Just to be more clear is there a difference between email: {type: String, index: {unique: true}} and email: {type: String, unique: true} while using mongoose? I mean I can set unique to be true for all the values in my Schema if I want, right? So what is an index with reference to my example above? This beginner post I am learning from and the docs confuse me about indexed a bit. :PKnockwurst
@Knockwurst If you are using mongoose I think email: {type: String, unique: true} might not work properly. I haven't tested it but might be like this: If your data values are there, then you added the key unique: true, should not work.(If no data there, haven't check). You should create the index in MongoDB shell then use mongoose. You can reference my another answer: https://mcmap.net/q/206605/-how-to-make-a-variable-a-unique-key-in-mongooseAmenity
@WilliamHu I just checked. What you proposed is correct. If there is some data already and I add unique: true the old data remains although it doesn't allow me to add new data which isn't unique. In that case, I will need dropDupsKnockwurst
@Knockwurst So, in that case, you don't need to use MongoDB shell. Just add dropDups then unique: true works, correct?Amenity
@WilliamHu Yes, it does as long as the index was created before the insertion of the docs. The mongoose documentation refers this to as a race. :P mongoosejs.com/docs/… So when I set dropDups, weather it saves first or creates index first one of those dropDups or unique kicks in. Does the job :)Knockwurst
Adding filed property like unique : true is worked for me after deleting all duplicate data that was saved before. setting unique : true ))Saree
K
0

In NextJS - Mongoose & unique field

import mongoose, { Schema } from "mongoose";
const UserSchema = new Schema({
 name : String,
 email:{
    type: String,
    required: [true,"email required!"],
    unique: true,
 },
 password:{
    type: String,
    required: [true,"password required!"],
    unique:true,
},
 about:String,
 profileURL:String,
//  address:{
//     street:String,
//     city:String,
//     Country:String,
//     PinCode:Number,
// },

});
Kayceekaye answered 17/3 at 14:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.