I am making a simple todo list application for educational purposes and i am using the custom route functionality,so if the user types a custom route,i am checking if a collection with that name exists in the db and if it does'nt i am creating it,but mongoose creates the same collection many times instead of one.
I am hitting my head on this,do you see something that could trigger this kind of issue in my code ?
const express = require("express")
const mongoose = require("mongoose");
const app = express()
const _ = require("lodash")
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true}))
app.use(express.static('static'));
app.use('/dep/css', express.static(`${__dirname}/node_modules/bootstrap/dist/css`))
app.use('/dep/js', express.static(`${__dirname}/node_modules/bootstrap/dist/js`))
app.use('/dep/js', express.static(`${__dirname}/node_modules/particlesjs/dist`))
app.use('/dep/js', express.static(`${__dirname}/node_modules/@fortawesome/fontawesome-free/js`))
// --------------------- CONNECTION -----------------------------
mongoose.connect('mongodb://localhost:27017/todoDB');
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection open to 27017');
});
// -------------------------- MODELS AND SCHEMAS -------------------
const itemsSchema = new mongoose.Schema({
task: {
type: String,
required: [true, "Task cannot be empty !"]
}
})
const Item = mongoose.model("Item", itemsSchema);
const listSchema = new mongoose.Schema({
name: {
type: String,
required: [true, "List name cannot be empty !"]
},
items : [itemsSchema]
})
const List = mongoose.model("List", listSchema);
const dateOptions = {
day:"numeric",
weekday:"long",
month : "long",
year : "numeric"
}
const currentDay = new Date().toLocaleDateString("en-US",dateOptions)
// --------------------- GETS ------------------------------------
app.get("/", (req, res) => {
Item.find((err, items) => {
if (err) {
console.log(err);
} else {
res.render('list', {
listName: currentDay,
newItems:items
});
}
})
})
app.get("/:customList", (req, res) => { //GET A REQUEST TO A CUSTOM ROUTE
const customList = _.capitalize(req.params.customList) //GRAB THE CUSTOM ROUTE STRING
List.findOne( {name:customList},(err,listFound) =>{ //SEARCH IF THE COLLECTION EXISTS
if (err){ console.log(err) }else{
if(listFound){ //IF IT EXISTS RENDER THE VIEW WITH THE COLLECTION DATA
res.render('list', {
listName: listFound.name,
newItems:listFound.items
});
}else{ //IF ITS NOT THEN CREATE IT WITH THE GIVEN NAME
const list = new List({
name:customList
})
list.save()
res.redirect(`/${customList}`)
console.log("list created !")
}
}
} )
})
// ------------------- POSTS ------------------------------
app.post("/", (req,res) =>{
let item = new Item({
task: req.body.newItem
})
if ( req.body.list === currentDay ){
item.save((err)=>{ err?console.log(err):console.log("saved") })
res.redirect("/")
}else{
List.findOne( {name:req.body.list},(err,listFound) =>{
if (err){ console.log(err) }else{
listFound.items.push(item)
listFound.save()
res.redirect(`/${req.body.list}`)
}
} )
}
} )
app.post("/delete", (req,res) =>{
if ( req.body.list === currentDay ){
Item.findByIdAndRemove({ _id: req.body.checkbox },(err)=>err?console.log(err):console.log("deleted"))
res.redirect("/")
}else{
List.findOneAndUpdate( {name:req.body.list},{ $pull: { items: {_id : req.body.checkbox} } },(err,listFound) =>{
err ? console.log(err) : res.redirect(`/${req.body.list}`)
})
}
})
// -------------------- SERVER --------------------------
const server = app.listen(3000, () => {
console.log(`Todolist app server is running on port ${server.address().port}`);
})
And this what i am getting from my db server after i create a collection,for example here i create a collection with name "yolo",and when i show my collections... :
> db.lists.find()
{ "_id" : ObjectId("61d9d2c74eff3d67c18430f1"), "name" : "Yolo", "items" : [ ], "__v" : 0 }
{ "_id" : ObjectId("61d9d2c74eff3d67c1843100"), "name" : "Yolo", "items" : [ ], "__v" : 0 }
{ "_id" : ObjectId("61d9d2c74eff3d67c18430f4"), "name" : "Yolo", "items" : [ ], "__v" : 0 }
{ "_id" : ObjectId("61d9d2c74eff3d67c18430f7"), "name" : "Yolo", "items" : [ ], "__v" : 0 }
{ "_id" : ObjectId("61d9d2c74eff3d67c18430fa"), "name" : "Yolo", "items" : [ ], "__v" : 0 }
{ "_id" : ObjectId("61d9d2c74eff3d67c18430fd"), "name" : "Yolo", "items" : [ ], "__v" : 0 }
CodePudding user response:
I think you are confused with the term collection with document, after querying find what you are getting is documents present in the List collection. you can do as below to make the name in the list as unique, however this is not the standard solution, for the property unique you might want to check the documentation here
const listSchema = new mongoose.Schema({
name: {
type: String,
required: [true, "List name cannot be empty !"],
unique: true
},
items : [itemsSchema]
})
const List = mongoose.model("List", listSchema);
CodePudding user response:
The save() function is asynchronous. When you call redirect
immediately after calling save
, you have a race condition, and it will continue to loop and call save followed by redirect until one of the save calls actually completes.
To fix this, move the redirect
call to a callback function passed to save