Reputation: 397
I have two schema collections:
Campaigns:{
_id: "someGeneratedID"
//...a lot of key value pairs.
//then i have teams which is an, array of teams from the Team schema.
teams:teams: [{ type: mongoose.Schema.Types.ObjectId, ref: "Team" }],
}
Teams:{
campaignId: { type: mongoose.Schema.Types.ObjectId, ref: "Campaign" },
isDefault: { type: Boolean, default: false },
}
Now I would like that when I add teams to the collection, it should throw an error if there are more than 2 isDefault:true
per campaignId
.
so the following shouldn't be allowed:
teams:[
{
campaignId:1,
teamName:"John Doe"
isDefault:true,
}
{
campaignId:1,
teamName:"Jane Doe"
isDefault:true
}
]
I found this answer on SO:
teamSchema.index(
{ isDefault: 1 },
{
unique: true,
partialFilterExpression: { isDefault: true },
}
But couldn't manage to also check for the campaignId.
Thanks in advance.
ps: can you also provide an explanation for what's happening in the index method?
Upvotes: 0
Views: 313
Reputation: 354
I think that the simplest way to approach this is via Mongoose's middleware pre('save')
. This method will give you a way to check all the campaigns listed in the collection in order to check if any of the items is already set as default.
teamSchema.pre("save", async function (next) {
try {
if ((this.isNew || this.isModified("isDefault") && this.isDefault) {
const previousDefault = await mongoose.models["Team"].findOne({ isDefault: true, campaignId: this.campaignId });
if (previousDefault) {
throw new Error('There is already default team for this campaign');
}
}
next();
} catch (error) {
throw error;
}
});
This way, if any team, either new or already existing, is set as default for a given campaign, before its record is saved, the whole collection will be searched for any entry with isDefault
already set to true
. If at least one item is found, we will throw an error. If not, next()
guarantees the save() method will go on.
Upvotes: 1