【问题标题】:Mongoose creates the same mongodb collection multiple times in one instanceMongoose 在一个实例中多次创建同一个 mongodb 集合
【发布时间】:2022-01-08 18:11:47
【问题描述】:

我正在为教育目的制作一个简单的待办事项列表应用程序,并且我正在使用自定义路由功能,因此如果用户键入自定义路由,我将检查数据库中是否存在具有该名称的文档以及是否存在nt 我正在创建它,但是 mongoose 多次创建同一个文档而不是一个。

我对此一头雾水,您是否在我的代码中看到了可能触发此类问题的内容?


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 DOCUMENT EXISTS
if (err){ console.log(err) }else{

if(listFound){   //IF IT EXISTS RENDER THE VIEW WITH ITS 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}`);
})


这是我在创建集合后从我的数据库服务器获得的内容,例如在这里我创建了一个名为“yolo”的集合,当我显示我的集合时...:


> 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 }

【问题讨论】:

    标签: javascript node.js mongodb express mongoose


    【解决方案1】:

    save() 函数是异步的。当您在调用 save 后立即调用 redirect 时,您会遇到竞争条件,它将继续循环并调用 save 然后重定向,直到其中一个 save 调用实际完成。

    要解决此问题,请将 redirect 调用移至传递给 save 的回调函数

    【讨论】:

    • 这个。我发现这与我在保存收藏后如何重定向有关。原来 save() 函数返回一个承诺,所以我只是链接了一个处理重定向的 .then 函数,它解决了这个问题。 list.save().then( () =>{ res.redirect(/${customList}) }) 谢谢!
    【解决方案2】:

    我认为您对带有文档的术语集合感到困惑,在查询后发现您得到的是列表集合中存在的文档。 您可以执行以下操作以使列表中的名称唯一,但这不是标准解决方案,对于唯一的属性,您可能需要查看文档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);
    

    【讨论】:

      猜你喜欢
      • 2019-01-06
      • 2013-10-20
      • 1970-01-01
      • 2017-06-14
      • 2011-09-24
      • 2020-07-17
      • 1970-01-01
      • 2016-04-01
      相关资源
      最近更新 更多