David Chanin
David Chanin

Reputation: 553

Validating uniqueness of an embedded document scoped by its parent in mongoose

I have the following schema in mongoose:

UserSchema = new Schema
    username: {type: String, required: true}

GameSchema = new Schema
    identifier: String
    users: [UserSchema]

I want to ensure that every user in a game has a unique username. However, if I add

unique: true

to the username definition, then it seems to enforce uniqueness across all games, not just within the game that the user resides. Also, if I have more than 1 game with no users, then I get the following error:

games.$users.username_1  dup key: { : null }

I tried adding a custom validator to the username field to manually check if that username is already taken within the scope of the parent game, but in mongoose the validator function only receives the actual string of the username, so I don't have any way of checking that the username is unique within the game because I can't get a reference to the parent game document in the validator function.

Is there any way to accomplish this sort of validation in mongoose?

Upvotes: 5

Views: 2506

Answers (2)

JohnnyHK
JohnnyHK

Reputation: 311865

As you found out, adding a unique index to a field of an array doesn't enforce uniqueness within the array, it ensures that no two documents in the collection contain the same field value in the array.

Instead, look at the $addToSet array operator as a way of atomically adding a value to an array only if it's not already in the array.

Upvotes: 5

chovy
chovy

Reputation: 75686

This is easily achieved by doing:

doc.array.addToSet(4,5);

You can remove them by doing:

doc.array.pull(4,5);
doc.array.remove(4,5); //alias of .pull()

http://mongoosejs.com/docs/api.html#types_array_MongooseArray-addToSet http://mongoosejs.com/docs/api.html#types_array_MongooseArray-pull

Upvotes: 1

Related Questions