2

I recognized this question has been asked before, but none of the solutions seemed to work for me.

I have a simple model I'm defining like this:

const mongoose = require('mongoose')
const { Schema } = mongoose

let subscriberSchema = new Schema({
  firstName: { type: String, required: true },
  email: { type: String, required: true, unique: true }
}, { timestamps: true })

let Subscriber = mongoose.model('Subscriber', subscriberSchema)

If I run the following (in the REPL, so no async issues), I'd expect to see an error being logged for the second call to create.

Subscriber.create({ firstName: "Landon", email: "example@example.com" })
Subscriber.create({ firstName: "Landon", email: "example@example.com" }, function(err) { 
  console.log("ERROR", err) 
})

Instead, I see "ERROR" null.

If I run a count query or a find query, I can see both models were created. What am I doing wrong?

Edit

Here are a few of the things I've already tried:

  • Restart MongoDB after adding index
  • Removing all of the existing records so there are no existing records that could violate the uniqueness constraint
  • Defining the email attribute all of these ways (I've seen different implementations in different places): { type: String, required: true, unique: true }, { type: String, required: true, index: true, unique: true }, { type: String, required: true, index: { unique: true } }.
Community
  • 1
  • 1
LandonSchropp
  • 10,084
  • 22
  • 86
  • 149

3 Answers3

3

This is very complicated thing to solve with node, as you know its async. If you are running both queries parallel, both will check if doc exists as same time and both will try to create the record.

There are two things you could do.

Create Unique Index

YourModel.index({ email: 1}, { unique: true })

OR
Use Update with $setOnInsert

var pk = {email : 'your email'};
YourModel.update(pk, {
        $setOnInsert : data
    }, {upsert : true})

And Make sure the index exists in mongoDB.

Mongoose does not modify index on key set. First try to remove index from mongo shell.

 db.collection.dropIndex({email : 1})

Restart node process and mongoose will now create index with unique constraint.

anwerj
  • 2,386
  • 2
  • 17
  • 36
  • I don't think I was clear in my question. The example `Subscriber.create` calls were in the Node REPL, so there shouldn't be any async issues. I ran the first create, waited for it to finish, and then ran the second. If I run subsequent calls to `create` later on I still see the same issues. – LandonSchropp May 15 '16 at 07:49
  • Whenever you add an index, you gotta restart the node process, Mongoose autoIndex will try to ensure indices. you can see that with mongoose debug on. And make sure indices are there in collection by *getIndexes()* – anwerj May 15 '16 at 07:54
  • I've tried restarting the server as well as mongod, but unfortunately that doesn't seem to help. Running `Scheduler.collection.getIndexes()` resolves to this: `{ _id_: [ [ '_id', 1 ] ], email_1: [ [ 'email', 1 ] ] }`. I don't see anything in there about uniqueness, but I'm not sure if I should, and I don't know how to fix it. – LandonSchropp May 15 '16 at 08:00
  • Oh, i got it mongoose does not modify index on one key set, you have to remove index with dropIndex from shell. then you will see unique index – anwerj May 15 '16 at 08:12
  • i have updated my answer, please accept if it works for you. – anwerj May 15 '16 at 08:22
  • It worked! Thanks so much for the help @anwerjunaid. :) – LandonSchropp May 15 '16 at 08:28
  • For anyone else who runs across this, I also had to fix the records that conflicted with the unique index before Mongoose would add it. – LandonSchropp May 15 '16 at 08:29
2

Actually, unique option for validation working,how?Follow these steps:
1)set unique: true for certain field in schema(example "email")
2)drop whole db
3)restart node server
4)test in postman and you will see than now works

Cheers.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
Goran_Ilic_Ilke
  • 812
  • 12
  • 16
0

Make autoIndex: true while connecting to the database.

mongoose
.connect('connection url', {
    useUnifiedTopology: true,
    useNewUrlParser: true,
    autoIndex: true, //make this true
})
.then(() => {
    console.log('Connected to mongoDB');
});