Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 434
David Chanin Avatar asked Dec 17 '12 01:12

David Chanin


2 Answers

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.

like image 149
JohnnyHK Avatar answered Nov 15 '22 04:11

JohnnyHK


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

like image 20
chovy Avatar answered Nov 15 '22 05:11

chovy