0

So I got two mongoose-models:

var mongoose = require('mongoose');
var Schema    = mongoose.Schema;
var eventSchema = new mongoose.Schema({

  name: String,
  date: String,
  dogs: [{ type: Schema.Types.ObjectId, ref: 'Dog' }]

});
module.exports = mongoose.model('Event', eventSchema);

and

var mongoose = require('mongoose');
var Schema    = mongoose.Schema;
var dogSchema = new mongoose.Schema({

  name: String,
  age: String,
  gender: String,

});
module.exports = mongoose.model('Dog', dogSchema);

Event contains an array of dogs and im trying to figure out how to add/delete dogs to this array.

On the client I got this method:

  $.ajax({
     url: "http://localhost:3000/api/events/",
     dataType: 'json',
     type: 'POST', // Not sure if I should Post or Put...
     data: {event_Id : this.props.choosenEvent._id, //Here I got the Id of the Event that i want to update by
            dog_Id : this.props.events[dog]._id }, //adding this dog, which Id is here
     success: function(data) {

     }.bind(this),
   });
 },

On the server, NodeJs, I got my routes to the API. To me, it makes sense to use an PUT-method and start by getting the right Event with the event_Id passed as a param. Something like:

router.route('/events/:event_id')
    .put(function(req, res) {


        Event
        .findById({ _id: req.param.event_id })
        .populate('dogs')

        });

But Im stuck at this point. Any help appreciated. Thanks!

Update!

Thank you! Your code helped a lot, you used lodash .remove to delete a dog from the array, is there a similar way to add an item with lodash?

I gave the add method a go like this:

router.route('/events')   
      .post(function(req, res) {
          // Your data is inside req.body

          Event
              .findById({ _id: req.body.event_Id })
              // execute the query
              .exec(function(err, eventData) {
                  // Do some error handing
                  // Your dogs are inside eventData.dogs
                  eventData.dogs.push(req.body.dog_Id);
                  console.log(eventData)

                });
                  // Update your eventDate here
                  Event.update({_id: req.body.event_id}, eventData)
                      .exec(function(err, update) {
                          // Do some error handing
                          // And send your response
                      });
              });

When I hit the console.log(eventData) I can see that dog_id gets added to the array as it should. However it does not get saved to the db and the error says that eventData is not defined in Event.Update. I suspect this is a Js-scope-issue.

Onte thing that boggles me is this:

Obviously I would like to be able to add and remove dogs from the array and the route is this: router.route('/events') .

But if both the add-method and the remove-method is on the same route, how can the code know which one I am going for?

user2915962
  • 2,691
  • 8
  • 33
  • 60

1 Answers1

1

There are a few mistakes you are making. First of all, you are making a POST request but your route accepts a PUT request. I have updated your code so it accepts a POST.

When posting objects, your data is inside req.body. req.params is used for url parameters. This is also the case when using a PUT request.

Populating dogs is not really necessary. You are sending your dog_id to your function so you can delete your item from your array which removes your dog from your event. This should do the trick. Please note that this does not remove your dog from your DB but only from your event.

Last but not least. I am using lodash. _.remove is a lodash function. You should definitely check it out, it will help you a lot.

Take a look at my code. It should get you going:

router.route('/events/:event_id')
    // Since you are posting, you should use POST from JavaScript instead of PUT
    .post(function(req, res) {
        // Your data is inside req.body
        Event
            .findById({ _id: req.body.event_id })
            // execute the query
            .exec(function(err, eventData) {
                // Do some error handing
                // Your dogs are inside eventData.dogs
                _.remove(eventData.dogs, function(d) {
                    return d._id === req.body.dog_Id;
                });
                // Update your eventDate here
                Event.update({_id: req.body.event_id}, eventData)
                    .exec(function(err, update) {
                        // Do some error handing
                        // And send your response
                    });
            });

        });

UPDATE:

I do not think there is a way to add items to an array with lodash but you can simply use push like you did in your code example. That works just fine.

Your update is not working because your are executing the findById and update at the same time. You will have to find the item first, add the id and THEN update the item :) Move your update function inside the callback of your findById function and that should be fixed. So it looks like this:

router.route('/events')   
    .post(function(req, res) {
        // Your data is inside req.body

        Event
        .findById({ _id: req.body.event_Id })
        // execute the query
        .exec(function(err, eventData) {
            // Do some error handing
            // Your dogs are inside eventData.dogs
            eventData.dogs.push(req.body.dog_Id);
            console.log(eventData)

            // Update your eventDate here
            Event.update({_id: req.body.event_id}, eventData)
            .exec(function(err, update) {
                // Do some error handing
                // And send your response
            });
        });
    });

You can add different functions on the same route as long as the method is different from the others. Take a look at REST at this answer. You can have a GET, POST, PUT & DELETE on /events. This is defined by this rule:

router.route('/events').post();
Community
  • 1
  • 1
Thomas Bormans
  • 5,156
  • 6
  • 34
  • 51