I’m using typegoose nested classes with mongoose-unique-validator as follows
import {
prop,
plugin,
post,
index,
getModelForClass,
} from "@typegoose/typegoose";
const uniqueValidator = require("mongoose-unique-validator");
@plugin(uniqueValidator, {
message: "{VALUE} already exists",
})
// ATTRIBUTES CLASS
class Attributes {
@prop({
default: false,
})
active: boolean;
}
export class Specie {
// NAME
@prop({
unique: true,
required: [true, "Name is required"],
})
name: string;
// NESTED ATTRIBUTES CLASS
@prop({ _id: false, unique: false })
attributes?: Attributes;
}
// EXPORT MODEL
export const SpecieModel = getModelForClass(Specie, {
existingMongoose: mongoose,
schemaOptions: {
collection: "species",
timestamps: true,
optimisticConcurrency: true,
toJSON: {
transform: (obj, ret) => {
delete ret.__v;
},
},
},
}) as PaginateModel<Specie, typeof Specie>;
When I remove nested object "Attributes" mongoose-unique-validator
works fine giving me the name of the duplicate field.
but when I use it with nested object "Attributes" & documents with duplicate names, I get
MongoServerError: E11000 duplicate key error collection : collection.species index: name_1 dup key: { name: "somename" }
I want to make use of unique: true
functionality of the mongoose.
Am I using the plugin/typegoose nested objects correctly? Why mongoose-unique-validator
not working as expected with typegoose nested object?
2
Answers
Based on the error message the problem seems to be that you try to create a
unique
constraint on data that is already not unique. The issue is that you already have duplicated names. You will need to perform some operations that are compatible with the needs of your project that end with a state that there are no longer duplicates of name.You may archive names (create another entity and insert all the duplicates into them except one for each duplicate, then remove the inserted records from the original entity), or you may simply remove all duplications of name, leaving any
name
values to exist once at most, or you can merge the duplications if they are interrelated.Basically you will need to make sure that your data already meets the
unique
constraint and only then add the constraint. Such a constraint will not do your work of figuring out how your data needs to be cleaned up (imagine if some software that’s unaware of your project’s needs just guesstimates how your data is to be cleaned up and acts upon it, causing you data loss), it is a work that you need to do. The constraint, instead of cleaning your existent data will make sure that future operations will not end up with duplicates onname
.From what i can tell
mongoose-unique-validator
is meant to search the database for each property that has aunique: true
option set to throw a custom error before asave
operation.You are applying the plugin to class
Attributes
, but are expecting the error to be thrown forSpecie
, which is not a extending class.TL;DR: you did not apply the plugin to the class
Specie
where you expected it.PS: you can globally apply plugins by using
mongoose.plugin
which will apply a plugin to all schemas for that mongoose instance defined after themongoose.plugin
call.