I am trying to seed my mongodb database and I am running into this Validation error.
the error:
ValidationError: food validation failed: _id: Cast to ObjectId failed for value "1" (type string) at path "_id" because of "BSONError"
at model.Document.invalidate (/backend/node_modules/mongoose/lib/document.js:3157:32)
at model.$set (/backend/node_modules/mongoose/lib/document.js:1453:12)
at model.set (/backend/node_modules/mongoose/lib/helpers/document/compile.js:205:19)
at model.idSetter (/backend/node_modules/mongoose/lib/helpers/schema/idGetter.js:41:12)
at VirtualType.applySetters (/backend/node_modules/mongoose/lib/virtualtype.js:166:16)
at model.$set (/backend/node_modules/mongoose/lib/document.js:1271:12)
at model.$set (/backend/node_modules/mongoose/lib/document.js:1113:16)
at model.Document (/backend/node_modules/mongoose/lib/document.js:164:12)
at model.Model (/backend/node_modules/mongoose/lib/model.js:122:12)
at new model (/backend/node_modules/mongoose/lib/model.js:4682:15)
my model.ts looks like:
export interface Food {
id: string;
name: string;
price: number;
tags: string[];
favorite: boolean;
stars: number;
imageUrl: string;
origins: string[];
cookTime: string;
url: string;
}
export const FoodSchema = new Schema<Food>(
{
name: {type: String, required: true},
price: {type: Number, required: true},
tags: {type: [String], required: true},
favorite: {type: Boolean, default: false},
stars: {type: Number, required: true},
imageUrl: {type: String, required: true},
origins: {type: [String], required: true},
cookTime: {type: String, required: true},
url: {type: String, required: true},
}, {
toJSON: {
virtuals: true
},
toObject: {
virtuals: true
},
timestamps: true
}
);
export const FoodModel = model<Food>('Food', FoodSchema);
and my seed api looks like:
router.get("/seed", asynceHandler(
async (req,res)=>{
const foodsCount = await FoodModel.countDocuments();
if(foodsCount>0){
res.send("Seed is already done");
return;
}
await FoodModel.create(sample_foods);
res.send("Seed is done")
}
))
What am I doing wrong? I am a newbie to Mongodb and trying to learn it with the help of a tutorial.
id: '1'
is not a valid id. The valid Id can be a 24 character hex string, 12 byte binary Buffer, or a number. Mongoose cast the id: '1'
to an ObjectId failed, that's why you got the error.
How does cast work? Mongoose will try to create the ObjectId using new bson.ObjectId('1')
, in the ObjectId
constructor, it will validate the input id and throw a BSONError
You have three choices:
If you want to use the _id
Mongoose added to the document, do:
create the ObjectId explicitly using new mongoose.Types.ObjectId()
Let the mongoose create ObjectId for you. You don't need to pass the id
field to the Food.create()
method.
If you want to create an id
field by yourself, do:
id
field with a String
type in the schema. But you have to maintain its uniqueness with a unique indexes.E.g.
import mongoose from 'mongoose';
import { config } from '../../config';
mongoose.set('debug', true);
console.log(mongoose.version);
const FoodSchema = new mongoose.Schema({
// id: String
name: String,
});
const Food = mongoose.model('Food', FoodSchema);
(async function main() {
try {
await mongoose.connect(config.MONGODB_URI);
// seed
const sample_foods = {
id: '1',
name: 'Pizza Pepperoni',
};
// create ObjectId explicitly
// await Food.create({ ...sample_foods, id: new mongoose.Types.ObjectId() });
// create ObjectId implicitly
const { id, ...rest } = sample_foods;
await Food.create(rest);
// declare an id field with the String type, then `id: '1'` is ok.
// await Food.create(sample_foods);
} catch (error) {
console.error(error);
} finally {
await mongoose.connection.close();
}
})();