Express/Mongoose Router: 'Cast to ObjectId failed for value “undefined” at path “_id”'

左心房为你撑大大i 提交于 2019-12-02 13:40:10

问题


I have a simple API in Express that allows the user to 'post' and 'delete' a post title into a MongoDB database. For some reason, when I add a post title, then subsequently 'delete' it, I get the "Cast to ObjectId failed for value "undefined" at path "_id".

It seems that the "_id" doesn't exist when I call 'delete' after I create the post. However, when I refresh the page, then click 'delete', it gets the "_id" perfectly fine and deletes the entry.

Am I doing something wrong in the routing to not have the "_id" generate and able to be pulled from the post immediately?

module.exports = function(router) {

    var Post = require('../models/post.js');

    // middleware for the api requests
    router.use(function(req, res, next) {
        // do logging
        console.log('something is happening.');
        next(); // make sure we go to our next route and don't stop here
    });

    // test route to make sure everything is working (accessed at GET http://localhost:8080/api)

    router.get('/', function(req, res) {
        res.json({ message: 'hooray! welcome to our api!' });   
    });

    // all routes here

    // routes that end in /posts
    router.route('/posts')

        // create a Post (accessed at POST http://localhost:7777/api/posts)
        .post(function(req, res) {
            var post = new Post();
            post.postTitle = req.body.postTitle; // set the post name (comes from request) 
            console.log(post._id);

            // save post and check for errors
            post.save(function(err) {
                if (err)
                    return res.status(300).send(err);

                res.json({ message: 'post created!' });
            });
        })

        // get all Posts (accessed at GET http://localhost:7777/api/posts)
        .get(function(req, res) {
            Post.find(function(err, posts) {
                if (err)
                    return res.send(err);

                res.json(posts);
            });
        });

    // routes that end in /posts for specific id
    router.route('/posts/:post_id')

        // get the post with that id
        .get(function(req, res) {
            Post.findById(req.params.post_id, function(err, post) {
                if (err)
                    return res.send(err);

                res.json(post);
            });
        })

        // update the post with that id
        .put(function(req, res) {
            Post.findById(req.params.post_id, function(err, post) {
                if (err)
                    return res.send(err);

                post.postTitle = req.body.postTitle;

                // save the post
                post.save(function(err) {
                    if (err)
                        return res.send(err);

                    res.json({ message: 'post updated!' });
                });
            });
        })

        // deletes the post with that id
        .delete(function(req, res) {
            Post.findOne({
                _id:req.params.post_id
            }).remove(function(x){
                console.log("removed: ", x);
            });
        })

        .patch(function(req, res) {
            Post.findOne({
                _id: req.body._id
            }, function(err, doc) {
                for (var key in req.body) {
                    dock[key] = req.body[key];
                }
                doc.save();
                res.status(200).send();
            });
        });
}

/

function addPostItem(post){
        posts.push(post);
        triggerListeners();

        helper.post("/api/posts", post);
    }

function deletePost(post) {
        var index = posts.indexOf(post);
        console.log(post);
        posts.splice(index, 1);
        triggerListeners();

        helper.del('api/posts/' + post._id);
    }

/

var $ = require('jquery');

module.exports = {
    get: function(url) {
        return new Promise(function(success, error) {
            $.ajax({
                url: url,
                dataType: 'json',
                success: success,
                error: error
            });
        });
    },
    post: function(url, data) {
        return new Promise(function(success, error) {
            $.ajax({
                url: url,
                type: 'POST',
                data: data,
                success: success,
                error: error
            });
        });
    },
    patch: function(url, data) {
        return new Promise(function(success, error) {
            $.ajax({
                url: url,
                type: 'PATCH',
                data: data,
                success: success,
                error: error
            });
        });
    },
    del: function(url) {
        return new Promise(function(success, error) {
            $.ajax({
                url: url,
                type: 'DELETE',
                success: success,
                error: error
            });
        });
    }
};

回答1:


In addPostItem you add the post to your client side list of models before you make the POST call. The newly created post you push onto the posts array will NOT have an _id, since it is generated on the server and not returned. As you pass the server an undefined _id to the server for this new post, any api calls against it will fail with the same error.

When you refresh the page and call your get function, all your posts have an _id so everything works correctly.

A typical pattern to follow would be to return created id (or the entire post) to the client on the post creation and then add that to your items array (something like this):

function addPostItem(post){
    triggerListeners();

    helper.post("/api/posts", post, function(res){
        posts.push(res.data);
    });
}

You'd also need to rewrite your POST request to return the created entity:

post.save(function(err) {
            if (err)
                return res.status(300).send(err, o);

            res.json(o);
        });

A variation would be to return just the ._id. Another would be to create the id on the client side, but then you lose some of the advantages of the native mongo ObjectIds.



来源:https://stackoverflow.com/questions/34985332/express-mongoose-router-cast-to-objectid-failed-for-value-undefined-at-path

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!