Reputation: 385
I am working on a app that uses databases and adds items to the user using the user ID which is its username, but when i try to add an item i get an error and i can't seem to figure out how to fix it. Here is the error:
(node:14352) UnhandledPromiseRejectionWarning: MongoError: E11000 duplicate key error collection: sermontracker.items index: _id_ dup key: { _id: "sdfa3asdf2@asdf" }
at Function.create (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\core\error.js:57:12)
at toError (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\utils.js:123:22)
at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\operations\common_functions.js:258:39
at handler (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\core\sdam\topology.js:943:24)
at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\cmap\connection_pool.js:350:13
at handleOperationResult (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\core\sdam\server.js:558:5)
at MessageStream.messageHandler (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\cmap\connection.js:277:5)
at MessageStream.emit (events.js:315:20)
at processIncomingData (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\cmap\message_stream.js:144:12)
at MessageStream._write (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongodb\lib\cmap\message_stream.js:42:5)
at doWrite (_stream_writable.js:403:12)
at writeOrBuffer (_stream_writable.js:387:5)
at MessageStream.Writable.write (_stream_writable.js:318:11)
at Socket.ondata (_stream_readable.js:716:22)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:295:12)
(node:14352) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:14352) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
And here is the code where and when the error happens:
app.post("/workspace", function (req, res) {
const date = req.body.input1;
const location = req.body.input2;
const title = req.body.input3;
const passage = req.body.input4;
const file = req.body.input5;
const item = new Item({
_id: userN,
date: date,
loc: location,
title: title,
passage: passage,
file: file
});
item.save();
res.redirect("/workspace");
});
Here is the full code:
var userN;
var defaultItems = [];
mongoose.connect('mongodb://localhost:27017/sermontracker',
{
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
}
);
const ItemSchema = new mongoose.Schema({
_id: String,
date: String,
loc: String,
title: String,
passage: String,
file: String
});
const Item = mongoose.model("Item", ItemSchema);
app.post("/login", async (req, res) => {
const { username, password } = req.body;
const user = await User.findOne({ username }).lean();
userN = username;
if (!user) {
return res.json({ status: 'error', error: 'Invalid username/password' })
}
if (await bcrypt.compare(password, user.password)) {
const token = jwt.sign({ id: user._id, username: user.username }, JWT_SECRET);
res.redirect('/workspace');
res.json({ status: 'ok', data: token });
}
res.json({ status: 'ok', error: 'Invalid user/password' });
});
app.post('/signup', async (req, res) => {
const { username, password: plainTextPassword } = req.body;
userN = username;
if (!username || typeof username !== 'string') {
return res.json({ status: 'error', error: 'Invalid username' });
}
if (!plainTextPassword || typeof plainTextPassword !== 'string') {
return res.json({ status: 'error', error: 'Invalid password' });
}
if (plainTextPassword.length < 5) {
return res.json({ status: 'error', error: 'Password too small. Should be atleast 6 characters long.' });
}
const password = await bcrypt.hash(plainTextPassword, 10);
try {
const response = await User.create({
_id: userN,
username,
password
});
console.log('user created succecfully: ', response);
res.redirect('/workspace');
} catch (error) {
if (error.code == 11000) {
return res.json({ status: 'error', error: 'Username already taken' });
}
throw error
}
res.json({ status: 'ok' });
const item1 = new Item({
_id: userN,
date: "Date",
loc: "Location",
title: "Title",
passage: "Passage",
file: "File"
});
defaultItems.push(item1);
});
app.get("/", function (req, res) {
res.render("home");
});
app.get("/change-password", function (req, res) {
res.render("changepass");
});
app.get("/signup", function (req, res) {
res.render("signup");
});
app.get("/login", function (req, res) {
res.render("login");
});
app.get("/workspace", function (req, res) {
Item.find({ _id: userN }, function (err, foundItems) {
if (foundItems.length == 0) {
Item.insertMany(defaultItems, function (err) {
if (err) {
console.log(err);
} else {
console.log("Added items");
}
});
res.redirect("/workspace");
} else {
res.render("workspace", { itemList: foundItems });
}
});
});
app.post("/workspace", function (req, res) {
const date = req.body.input1;
const location = req.body.input2;
const title = req.body.input3;
const passage = req.body.input4;
const file = req.body.input5;
const item = new Item({
_id: userN,
date: date,
loc: location,
title: title,
passage: passage,
file: file
});
item.save();
res.redirect("/workspace");
});
The code looks like it would work but it doesn't. every time i try to add another item to a user then it gives me the error.
Upvotes: 2
Views: 171
Reputation: 63
From the MongoDB BSON guide "The field name _id is reserved for use as a primary key; its value must be unique in the collection, is immutable, and may be of any type other than an array."
So it would seem you are trying to add 2 documents with the same _id value. The field is automatically indexed to be unique, so if you can be sure that the username is and needs to be unique, you can continue using it, but if there can be multiple same usernames, you should save it to a separate field and leave the _id be.
Upvotes: 1