简体   繁体   中英

How can i splice an item from a mongoose schema then save the document or schema?

I am having trouble deleting items from an array that is inside the User schema then when i try to save the document it gives me this error?

Here is the error:

TypeError: User.save is not a function
    at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\app.js:194:10
    at Layer.handle [as handle_request] (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\express\lib\router\layer.js:95:5)
    at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\express\lib\router\index.js:281:22
    at Function.process_params (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\express\lib\router\index.js:275:10)
    at SessionStrategy.strategy.pass (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\passport\lib\middleware\authenticate.js:343:9)
    at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\passport\lib\strategies\session.js:69:12
    at pass (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\passport\lib\authenticator.js:337:31)
    at deserialized (C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\passport\lib\authenticator.js:349:7)
    at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\app.js:71:9
    at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongoose\lib\model.js:4866:16
    at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongoose\lib\model.js:4866:16
    at C:\Users\Children\Desktop\Web Projects\Sermon_Tracker\node_modules\mongoose\lib\helpers\promiseOrCallback.js:24:16

Here is where the error is in the code:

app.post("/delete", function (req, res) {

    const delBut = req.body.deleteItem;

    console.log(delBut);

    User.find({ _id: req.user._id }, function (err, foundItemList) {
        if (err) {
            console.log(err);
        } else {
            if (foundItemList) {
                for (var i = 0; i < foundItemList.length; i++) {
                    var itemList = foundItemList[i].items;
                    console.log(itemList);
                    itemList.forEach(function (item) {
                        console.log(item._id);
                        if (item._id == delBut) {
                            console.log("Found it!");
                            foundItemList[i].items.splice(i, 1);
                            console.log("Deleted it!");
                            console.log(itemList);
                        }
                    });
                }
            }
        }
    });

    User.save(function () {
        res.redirect('/workspace')
    });
})

Here is the full code:

//jshint esversion:6
require('dotenv').config();
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const session = require('express-session');
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const findOrCreate = require('mongoose-findorcreate');



const app = express();

const Schema = mongoose.Schema;

app.use(express.static("public"));
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
    extended: true
}));

app.use(session({
    secret: "Our little item.",
    resave: false,
    saveUninitialized: false
}));

app.use(passport.initialize());
app.use(passport.session());

const url2 = "mongodb://localhost:27017/sermontracker";

mongoose.connect(url2, { useNewUrlParser: true, useUnifiedTopology: true });
mongoose.set("useCreateIndex", true);

const userSchema = new mongoose.Schema({
    fname: String,
    lname: String,
    email: String,
    password: String,
    googleId: String,
    items: Array
});

const ItemSchema = new mongoose.Schema({
    date: String,
    loc: String,
    title: String,
    passage: String,
    file: String
});

userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);

const User = new mongoose.model("User", userSchema);
const Item = mongoose.model("Item", ItemSchema);

passport.use(User.createStrategy());

passport.serializeUser(function (user, done) {
    done(null, user.id);
});

passport.deserializeUser(function (id, done) {
    User.findById(id, function (err, user) {
        done(err, user);
    });
});

passport.use(new GoogleStrategy({
    clientID: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    callbackURL: "http://localhost:3000/auth/google/secrets",
    userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
    function (accessToken, refreshToken, profile, cb) {
        console.log(profile);

        User.findOrCreate({ googleId: profile.id }, function (err, user) {
            return cb(err, user);
        });
    }
));

app.get("/", function (req, res) {
    res.redirect("/home");
});

app.get("/home", function (req, res) {
    res.render("home");
});

app.get("/login", function (req, res) {
    res.render("login");
});

app.get("/signup", function (req, res) {
    res.render("signup");
});

app.get("/workspace", function (req, res) {
    User.find({ _id: req.user._id }, function (err, foundItems) {
        if (err) {
            console.log(err);
        } else if (foundItems) {
            for (var i = 0; i < foundItems.length; i++) {
                res.render("workspace", { itemList: foundItems[i].items });
            }
        }

    });


});


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({
        date: date,
        loc: location,
        title: title,
        passage: passage,
        file: file
    });

    User.findById(req.user._id, function (err, foundUser) {
        if (err) {
            console.log(err);
        } else {
            if (foundUser) {
                foundUser.items.push(item);
                foundUser.save(function () {
                    res.redirect("/workspace");
                });
            }
        }
    });
});

app.get("/workspaceLight", function (req, res) {
    User.find({ _id: req.user._id }, function (err, foundItems) {
        if (err) {
            console.log(err);
        } else if (foundItems) {
            for (var i = 0; i < foundItems.length; i++) {
                res.render("workspaceLight", { itemList: foundItems[i].items });
            }
        }

    });


});

app.post("/delete", function (req, res) {

    const delBut = req.body.deleteItem;

    console.log(delBut);

    User.find({ _id: req.user._id }, function (err, foundItemList) {
        if (err) {
            console.log(err);
        } else {
            if (foundItemList) {
                for (var i = 0; i < foundItemList.length; i++) {
                    var itemList = foundItemList[i].items;
                    console.log(itemList);
                    itemList.forEach(function (item) {
                        console.log(item._id);
                        if (item._id == delBut) {
                            console.log("Found it!");
                            foundItemList[i].items.splice(i, 1);
                            console.log("Deleted it!");
                            console.log(itemList);
                        }
                    });
                }
            }
        }
    });

    User.save(function () {
        res.redirect('/workspace')
    });
})


app.post("/workspaceLight", 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({
        date: date,
        loc: location,
        title: title,
        passage: passage,
        file: file
    });

    User.findById(req.user._id, function (err, foundUser) {
        if (err) {
            console.log(err);
        } else {
            if (foundUser) {
                foundUser.items.push(item);
                foundUser.save(function () {
                    res.redirect("/workspaceLight");
                });
            }
        }
    });
});

app.get("/logout", function (req, res) {
    req.logout();
    res.redirect("/home");
});
app.post("/logout", function (req, res) {
    req.logout();
    res.redirect("/home");
});

app.post("/signup", function (req, res) {

    User.register({ username: req.body.username, fname: req.body.firstName, lname: req.body.lastName }, req.body.password, function (err, user) {
        if (err) {
            console.log(err);
            res.redirect("/signup");
        } else {
            passport.authenticate("local")(req, res, function () {
                res.redirect("/workspace");
            });
        }
    });

});

app.post("/login", function (req, res) {

    const user = new User({
        username: req.body.username,
        password: req.body.password
    });

    req.login(user, function (err) {
        if (err) {
            console.log(err);
        } else {
            passport.authenticate("local")(req, res, function () {
                res.redirect("/workspace");
            });
        }
    });

});


app.listen(3000, function () {
    console.log("Server started on port 3000.");
});

How can i save the document or schema after i have spliced an item from the array?

You are trying to call the save method on modal but instead, you should call it on a modal instance.

for (var i = 0; i < foundItemList.length; i++) {
    var itemList = foundItemList[i].items;
    console.log(itemList);
    itemList.forEach(function (item) {
        console.log(item._id);
        if (item._id == delBut) {
            console.log("Found it!");
            foundItemList[i].items.splice(i, 1);
            console.log("Deleted it!");
            console.log(itemList);
        }
    });

    foundItemList[i].save(); // <---- save this
}

And when you are out of the loop

res.redirect('/workspace')

it would be better if you use async-await in this case.


Edit: Adding async-await version. I have not tested it yet, please test it at your end.

// adding async keyword
app.post("/delete", async function (req, res) {

    const delBut = req.body.deleteItem;

    console.log(delBut);

    try {
        let foundItemList = await User.find({ _id: req.user._id });
        if (foundItemList && foundItemList.length) {
            for (var i = 0; i < foundItemList.length; i++) {
                var itemList = foundItemList[i].items;
                console.log(itemList);
                for(let item of itemList) {
                    console.log(item._id);
                    if (item._id == delBut) {
                        console.log("Found it!");
                        foundItemList[i].items.splice(i, 1);
                        console.log("Deleted it!");
                        console.log(itemList);
                    }
                }

                await foundItemList[i].save(); // <---- save this
            }
        }
    } catch (error) {
        console.error(error);
    }

    res.redirect('/workspace');
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM