0

Im under the assumption that adding unique: true to a field would stop from saving to the database using the same value. But im still allowed to do it.

"mongoose": "^5.4.19",

const SessionSchema = new Schema({

    jobId: {
        type: String,
        required: false,
        unique: true,
        index: true,

    },
    productId: {
        type: String,
        required: true,
    },
    status: {
        type: String,
        default: "Pending",
    },
    mode: {
        type: String,
        default: "authentication",
    },
    result: {
        type: Schema.Types.Mixed,
    },
    requests: [RequestSchema],
    callback_at: {
        type: Date,
    },

}, {
        timestamps: { createdAt: "created_at", updatedAt: "updated_at" },
    });

I have already tried deleting and recreating the collection. See the image below i can create new session with the same jobId being 1.

enter image description here

public store = async (req: Request, res: Response): Promise<any> => {

        const input = req.body;

        let session = new Session({
            productId: input.productId,
            jobId: input.jobId,
        });

        try {

            session = await session.save();

            const response = {
                success: true,
                status: 201,
                data: { session },
                message: "SESSION CREATED",
            };


            return res.status(response.status).json(response);

        } catch (err) {

            const response = {
                success: false,
                status: 500,
                errors: [],
                message: "UNEXPECTED SESSION ERROR",
            };

            if (err.code === 11000) {
                response.errors.push({
                    code: 11000,
                    message: "Duplicate key error jobId",
                });
            }


            return res.status(response.status).json(response);
        }

db.sessions.getIndex();

[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "myDB.sessions"
    }
]
Kay
  • 17,906
  • 63
  • 162
  • 270
  • Can you update your question to show the output from `db.sessions.getIndexes()` (assuming that's your collection's name)? – JohnnyHK Mar 15 '19 at 16:38
  • Since adding the `unique: true` field, did you restart mongo? Related issue(?): https://stackoverflow.com/questions/5535610/mongoose-unique-index-not-working – Andrew Cameron Mar 15 '19 at 16:38
  • @AndrewCameron yep and i just tried again to make sure, i am running mongo in a docker container and i did stop and start on the mongo container. – Kay Mar 15 '19 at 16:40
  • That answer is so misleading. You don't need to restart mongodb to make a unique index functional. I wish we could get rid of that misinformation. – JohnnyHK Mar 15 '19 at 16:44
  • @JohnnyHK i have updated the original question with the output. Looks like jobId is not there but why... – Kay Mar 15 '19 at 16:48
  • 1
    So i just saw this - https://mongoosejs.com/docs/validation.html#the-unique-option-is-not-a-validator – Kay Mar 15 '19 at 16:55
  • Are you setting `autoIndex: false` in your `mongoose.connect` call? If so, you can call `Sessions.ensureIndexes()` to manually prompt the creation. – JohnnyHK Mar 15 '19 at 16:56
  • in my mongoose.connect options i have options: { useNewUrlParser: true, useCreateIndex: true, }, – Kay Mar 15 '19 at 16:59
  • So i should do await Sessions.ensureIndexes() before doing sessions.save(), ? – Kay Mar 15 '19 at 17:00
  • No, my guess is that the index creation is failing due to existing documents with duplicate `jobId`s. See [here](https://stackoverflow.com/questions/12452865/mongoose-not-creating-indexes/12453041#12453041) for how you can debug this. – JohnnyHK Mar 15 '19 at 17:06
  • @JohnnyHK well i am working locally so i just can delete the db and recreate. so i dont think thats the case – Kay Mar 15 '19 at 17:08
  • After deleting everything im still able to make duplicates – Kay Mar 15 '19 at 17:14
  • Adding ` autoIndex: true,` to my mongoose connect options seem to work nicely – Kay Mar 15 '19 at 17:27

2 Answers2

5

You have to understand that unique is an index configuration option in your schema.

For instance, if the users collection doesn't have a unique index on userName, then you need to wait for the index to build before you start relying on it.

 const user = new mongoose.Schema({
    userName: { type: 'String', unique: true },

  });

    const User = db.model('User', user);

      const doc = new User({
        userName: 'Bob'
      });

      return User.init() // `User.init()` returns a promise that is fulfilled when all indexes are done
        .then(() => User.create(doc))
        .then(() => User.create({ userName: 'Bob' }));
    }
Lii
  • 11,553
  • 8
  • 64
  • 88
0

I was not using unique properly: https://mongoosejs.com/docs/validation.html#the-unique-option-is-not-a-validator

Need to wait until the indexes are built before relying on unique to be a validator.

I changed my mongoose connect options to look like the following

 options: {
        useNewUrlParser: true,
        useCreateIndex: true,
        autoIndex: true,
    },

I;m not sure if its the most appropriate solution, but its the one ive gone with for now.

Kay
  • 17,906
  • 63
  • 162
  • 270