Reputation: 363
I have a state model which is a lookup with just a name that i have set to unique because i don't want two states with the same name. now I have vacation model with a state property that i have set to the state schema. error E11000 duplicate key error collection is thrown after the first vacation is inserted when I insert a second vacation with the same state.I know mongodb throws the exception because I already have a vacation with the state.name as the first one.
const stateSchema = new mongoose.Schema({
name: {
type: String,
required: true,
minlength: 1,
maxlength: 30,
unique: true
}
});
const State = mongoose.model("State", stateSchema);
------------------------------------------------------
const vacationSchema = new mongoose.Schema({
-- some properties
state: {
type: stateSchema,
required: true
}
-- some properties
});
const Vacation = mongoose.model("Vacation", vacationSchema);
so how can i force unique state names in the states collection, but allow multiple vacations to have the same state in the vacations state? do I have to explicitly change state: {type: stateSchema} to {type: new Schema(...etc ?
Upvotes: 0
Views: 757
Reputation: 17915
You've two options :
If there is only one field name in State collection, also if it doesn't change(kind of nothing like rename/alter), Plus every vacation document contains only one state name then you would include state name value in state field directly in your Vacation document, this helps in if you don't want to hit other collection every time you query Vacation plus no need to maintain two collections. There is no point of directly storing names in Vacation collection if you're maintaining State collection, as there won't be any validation whether a given name exists in State collection or not, unless you do a DB call to check it before inserts to Vacation, because storing data into collections is independent - So you might need to remove unique : true
from stateSchema
, your code should work, as the above code is about storing data into Vacation or simply in Vacation schema make State as string & use State schema for storing data into State Collection.
Or if you really need to maintain another collection as what you've now, then you need to have a mapping between documents in State collection to documents in Vacation. This is helpful if most documents in Vacation will have multiple State names in array field. Where State names are unique in State collection. Optimal way of having relation is thru _id
of State documents. If need to do that then make changes in Vacation Schema as,
state: {
type: [{ type: Schema.Types.ObjectId, ref: 'State' }],// you can make this single value instead of array.
required: true
}
After this you need to use .populate() on reads - Ref : mongoose populate
If you want to store state name as value in Vacation collection, then make state field as string, then you can use .populate() on reads - Ref : mongoose populate virtuals or similar to mongoDB's native $lookup
- Ref : mongoDB $lookup
Note :
unique
index on a field, that way it will be on DB level which helps either way when running queries directly on DB or thru code, whereas mongoose schema triggers thru code, Also when you create an unique index on existing collection & runs into issue means there is already duplicate data for that field.Upvotes: 1