Prevent duplicate entries to be created in MongoDB query

I have a mongodb collection that is of the following schema:
const ArtistSchema = new mongoose.Schema({
firstname: {
type: String,
required: true,
maxlength: [30, 'Max allowed 30 chars'],
},
lastname: {
type: String,
maxlength: [30, 'Max allowed 30 chars'],
default: '',
},
url: {
type: String,
default:
'https://cdn.vectorstock.com/i/preview-1x/48/06/image-preview-icon-picture-placeholder-vector-31284806.jpg',
},
});
const ArtistSchema = new mongoose.Schema({
firstname: {
type: String,
required: true,
maxlength: [30, 'Max allowed 30 chars'],
},
lastname: {
type: String,
maxlength: [30, 'Max allowed 30 chars'],
default: '',
},
url: {
type: String,
default:
'https://cdn.vectorstock.com/i/preview-1x/48/06/image-preview-icon-picture-placeholder-vector-31284806.jpg',
},
});
Now whenever I enter a new entry using an http POST request, the new entry is created even if the firstName and lastName is the same as that of an existing object in the collection. Here is the controller I am using for the POST logic:
const postOneArtist = async (req, res) => {
try {
const artist = await Artists.create(req.body);
res.status(201).json({ msg: 'Artist Added succesfully', artist });
} catch (error) {
console.log(error);
res.status(500).json({ err: error.name, msg: error.message });
}
};
const postOneArtist = async (req, res) => {
try {
const artist = await Artists.create(req.body);
res.status(201).json({ msg: 'Artist Added succesfully', artist });
} catch (error) {
console.log(error);
res.status(500).json({ err: error.name, msg: error.message });
}
};
I want The data to be created only if it is unique i.e. Both the firstName and lastName from the request should not match an object in the collection. How do I go about it?
17 Replies
ErickO
ErickOā€¢11mo ago
https://www.mongodb.com/docs/v6.0/core/index-unique/#unique-compound-index I believe the only way to achieve it in this awful db is to create a compound index and ensure uniqueness
Senra
Senraā€¢11mo ago
šŸ„² Okay I kind of understood how to create the compound index, but is there any way I can just create the coumpund index in my Schema file instead of using the mongo shell?
ErickO
ErickOā€¢11mo ago
šŸ¤” oh it says mongosh there but you don't have to use it one sec https://mongoosejs.com/docs/guide.html#indexes there's performance concerns (they mention it) with this approach but frankly if performance was a concern mongo wouldn't be your db so you're good to use this
Senra
Senraā€¢11mo ago
okay Ill check that out
ErickO
ErickOā€¢11mo ago
userSchema.index({ firstName: 1, lastName: 1 }, { unique: true }); generally you can almost go between mongodb docs and any other library that is a wrapper around mongodb as you see, mongo doesn't mention the fact that you can have a unique constrain but the syntax is the same as shown in the mongodb docs { groupNumber: 1, lastname: 1, firstname: 1 }, { unique: true } this can be very helpful, if you see that mongo can do something but mongoose doesn't mention it, they can do it too 99% of the time also just to be clear here, this returns an error it doesn't just drop the duplicated doc so if you're doing a bulk save and one of them is duplicate the whole thing fails, just something to keep in mind
Senra
Senraā€¢11mo ago
Ohh I see Okay, for some reason, it is not working as expected I am still able to add duplicate entries even with the index
ErickO
ErickOā€¢11mo ago
has to go before the function like
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
});

userSchema.index({ firstName: 1, lastName: 1 }, { unique: true });

const User = mongoose.model('User', userSchema);

module.exports = User;
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
});

userSchema.index({ firstName: 1, lastName: 1 }, { unique: true });

const User = mongoose.model('User', userSchema);

module.exports = User;
yeh? you might need to restart your mongo instance too
Senra
Senraā€¢11mo ago
Hmm I tried that still did not work. I restarted the mongo instance also But I found a primitive workaround for that (though might not be the most optimal way of doing it)
const postOneArtist = async (req, res) => {
const exist = await Artists.find({
firstname: req.body.firstname,
lastname: req.body.lastname ? req.body.lastname : '',
});
if (exist) {
return res
.status(500)
.json({
err: 'Duplicate Entry Error',
msg: 'The data you have entered is a duplicate. Please enter different value',
});
}
try {
const artist = await Artists.create(req.body);
res.status(201).json({ msg: 'Artist Added succesfully', artist });
} catch (error) {
console.log(error);
res.status(500).json({ err: error.name, msg: error.message });
}
};
const postOneArtist = async (req, res) => {
const exist = await Artists.find({
firstname: req.body.firstname,
lastname: req.body.lastname ? req.body.lastname : '',
});
if (exist) {
return res
.status(500)
.json({
err: 'Duplicate Entry Error',
msg: 'The data you have entered is a duplicate. Please enter different value',
});
}
try {
const artist = await Artists.create(req.body);
res.status(201).json({ msg: 'Artist Added succesfully', artist });
} catch (error) {
console.log(error);
res.status(500).json({ err: error.name, msg: error.message });
}
};
So I first find an existing entry in the collection, and add the new entry only if that does not exist Man this database sounds simple, but can create massive problems. Should just stick to Postgres
ErickO
ErickOā€¢11mo ago
as someone with over 3 years of experience with mongo... it's the bane of my existence I want my SQL back šŸ˜©
const postOneArtist = async (req, res) => {
const exist = await Artists.find({
firstname: req.body.firstname,
lastname: req.body.lastname ?? '',
});
const postOneArtist = async (req, res) => {
const exist = await Artists.find({
firstname: req.body.firstname,
lastname: req.body.lastname ?? '',
});
you can do that for lastname btw anyway no ide what's up with your thing, maybe you're using an older mongoose/mongo version? no idea also
MongoDB cannot create a unique index on the specified index field(s) if the collection already contains data that would violate the unique constraint for the index.
maybe if you delete all docs and try again it works? shrug
Senra
Senraā€¢11mo ago
oh will try that Yeah its around 1 to 1.5 years old Okay So I dropped the whole collection and inserted a few values again. Got this kind of error on all entries other than the first one:
{
"err": "MongoServerError",
"msg": "E11000 duplicate key error collection: SongList.artists index: firstName_1_lastName_1 dup key: { firstName: null, lastName: null }"
}
{
"err": "MongoServerError",
"msg": "E11000 duplicate key error collection: SongList.artists index: firstName_1_lastName_1 dup key: { firstName: null, lastName: null }"
}
ErickO
ErickOā€¢11mo ago
{ firstName: null, lastName: null } seems like your first name and last name are empty check that your post request is working properly req.body might be empty or not parsed idk
Senra
Senraā€¢11mo ago
yup I double checked the post request. And even logged it. The post is working Correctly The only conclusion I got to was that my Mongoose is too outdated, and I need to update that.
ErickO
ErickOā€¢11mo ago
šŸ¤” you should check the version and check the docs go to the right version and see if the index works the same I remember older versions used some ensureIndex or some stuff but not sure
Senra
Senraā€¢11mo ago
Okay.... this might be a bit dumb, but I have camelCased the fields in the index. Hence it is returning null šŸ„² Now It works perfectly fine, as expected.
ErickO
ErickOā€¢11mo ago
PepeLaugh
Senra
Senraā€¢11mo ago
Thanks for the help šŸ«”
ErickO
ErickOā€¢11mo ago
np