Trouble with PUT request using Node.js (express), Angular, and MongoDB

回眸只為那壹抹淺笑 提交于 2019-11-30 19:57:01

问题


I'm stuck trying to figure out how to update my data to MongoDB (I'm using Monk with MongoDB, Node, Express, and Angular). I have no trouble with POST and DELETE, but can't figure out where I'm going wrong with PUT.

Error I get:

PUT http://localhost:3000/api/habits/[object%20Object] 500 (Internal Server Error) 

Where I'm confused is with what I should be sending with Angular, and how to receive it in Node, since I understand I need to send the updated object for the record, but then how should I be accessing the ID to look it up in Mongo?

For example with my POST (more code context below), it makes sense that I'm sending the object "newHabitData"

$http.post('http://localhost:3000/api/habits', newHabitData)

But with PUT examples I see, they send the object (named id) as a :parameter

app.put('/api/articles/:id', function (req, res){

I've been using these tutorial which is the closest I could find to understanding how to use PUT: http://aleksandrov.ws/2013/09/12/restful-api-with-nodejs-plus-mongodb/ http://scotch.io/tutorials/javascript/build-a-restful-api-using-node-and-express-4

A million thanks for some advice!

ANGULAR:

// Works Fine
$scope.addHabit = function(){
    var newTitle = $scope.newTitle.trim();
    if(!newTitle){
        return;
    }
    var newHabitData = {
        title: newTitle,
        count: 0,
        status: 'active'
    };

    $http.post('http://localhost:3000/api/habits', newHabitData)
        .success(function(data) {
            $scope.habitList = data;
            console.log(data);
        })
        .error(function(data) {
            console.log('Error: ' + data);
        });

    $('.habit-form__input-title').val('').focus();
    $scope.newTitle = '';

}

// Works Fine
$scope.habitDestroy = function (id) {       
    $http.delete('/api/habits/' + id._id)
        .success(function(data) {
            $scope.habitList = data;
            console.log(data);
        })
        .error(function(data) {
            console.log('Error: ' + data);
        });
};

// NOT WORKING - I WANT TO INCREMENT THE COUNT, THEN SAVE
$scope.habitCheckIn = function(id){             
    id.count = ++id.count;

    $http.put('/api/habits/' + id)  // Should I be sending the entire object? Seems to make most sense to me
        .success(function(data) {
            $scope.habitList = data;
            console.log(data);
        })
        .error(function(data) {
            console.log('Error: ' + data);
        });
}

NODE:

// Get all habits -- WORKS FINE
router.get('/api/habits', function(req, res) {
    var db = req.db;
    var collection = db.get('habits');
    collection.find({},{},function(e,data){
        res.json(data);
    });
});

// Create one habit -- WORKS FINE
router.post('/api/habits', function(req, res) {
    var db = req.db;
    var collection = db.get('habits');
    collection.find({},{},function(e,data){     
        collection.insert({ 
            title: req.body.title, 
            count: req.body.count  
        }, function(err, habit){
            if(err){
                res.send(err);
            }

            collection.find({},{},function(e,data){
                res.json(data);
            });
        });
    });
});

// Delete one habit -- WORKS FINE
router.delete('/api/habits/:habit_id', function(req, res){
    var db = req.db;
    var collection = db.get('habits');

    collection.find({},{},function(e,data){ 
        collection.remove({
            _id : req.params.habit_id
        }, function(err, todo){
            if(err){
                res.send(err);
            }

            collection.find({},{},function(e,data){
                res.json(data);
            });
        })
    })
})

// Update Habit -- NOT WORKING    
router.put('/api/habits/:habit_id', function(req, rest){
    var db = req.db;
    var collection = db.get('habits');

    // the real ID is _id, so should I be doing req.params.habit_id._id ? Or is findById asking for the entire object, and it finds the actual id itself? This is where I'm lost, can't figure it out.
    collection.findById(req.params.habit_id, function(e,data){  
        if(e){ res.send(e); }
        data.title = req.body.title;
        data.count = req.body.count;
        data.save(function(err){
            if(err){
                res.send(err);
            res.json(data);
            }
        })
    })
})

UPDATE - THE CODE BELOW GOT IT TO WORK. Thanks to saintedlama for getting me in the right direction.

Not sure if this is the right way to do it, but it works. I followed my POST format by accessing the req.body values, not the id passed in as a parameter.

So instead of this:

router.put('/api/habits/:habit_id', function(req, res) {

I did this:

router.put('/api/habits', function(req, res) {

Then I accessed the id and the updated count/title using the req.body._id and req.body.count values

router.put('/api/habits', function(req, res) {
    var db = req.db;
    var collection = db.get('habits');
    var id = req.body._id;

    if(!req.body) { 
        return res.send(400); 
    } // 6

    collection.findById(id, function(e,data){  
        if(e) { 
            return res.send(500, e); 
        } // 1, 2

        if(!data) { 
            return res.send(404); 
        } // 3

        var update = { 
            title : req.body.title, 
            count : req.body.count 
        }; // 4

        collection.updateById(id, update, function(err) { // 5
            if(err) {
                return res.send(500, err);
            }

        });
    });
});

回答1:


The code fragment to update existing habits should work just fine with some small corrections

  1. When running in an error always use return
  2. Always send a status back. In this case we'll send 500
  3. Check for not found and return 404
  4. Use simple update object. This will only update fields contained in the update object
  5. The mongodb document returned by monk has no save function, the document needs to be updated via the collection
  6. Check if the request has a body and send 400 - Bad Request

You can pass a object id as hex or ObjectId to findById as stated in the Monk docs.

router.put('/api/habits/:habit_id', function(req, rest){
    var db = req.db;
    var collection = db.get('habits');

    if(!req.body) { return res.send(400); } // 6

    collection.findById(req.params.habit_id, function(e,data){  
        if(e) { return res.send(500, e); } // 1, 2

        if(!data) { return res.send(404); } // 3

        var update = { title : req.body.title, count : req.body.count }; // 4

        collection.updateById(req.params.habit_id, update, function(err) { // 5
            if(err) {
                return res.send(500, err);
            }

            res.json(data);
        });
    });
});

The code above can be further simplified by using the findAndModify function of Monk.




回答2:


You have to do like:

model:

/**
 * Statics
 */
PostSchema.statics.load = function(id, cb) {
    this.findOne({
        _id: id
    }).populate('user', '_id name username email role').exec(cb);
};

controller:

exports.post = function(req, res, next, id) {
    if (!/^[0-9a-fA-F]{24}$/.test(id)) {
        return res.jsonp(404,{
            error: 'Failed to load post with id ' + id
        });
    }
    Post.load(id, function(err, post) {
        if (err) {
            return next(err);
        }
        if (!post){
            return res.jsonp(404,{
                error: 'Failed to load post with id ' + id
            });
        }
        req.post = post;
        next();
    });
};

route:

app.put('/admin/api/post/:postId', postController.update);
 app.param('postId', postController.post);

take a look at

http://expressjs.com/api#router.param

BTW

.success(function(data) {
            $scope.habitList = data;
            console.log(data);
        })

should be

.success(function(data) {
            $scope.habitList = data.data;
            console.log(data.data);
        })


来源:https://stackoverflow.com/questions/25408243/trouble-with-put-request-using-node-js-express-angular-and-mongodb

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