23

I'm trying to update an instantiated model ('Place' - I know it works from other routes) in a MongoDB and have spent a while trying to properly do so. I'm also trying to redirect back to the page that views the 'place' to view the updated properties.

Node v0.4.0, Express v1.0.7, Mongoose 1.10.0

Schema:

var PlaceSchema = new Schema({
name  :String
,  capital: String
,  continent: String
});

Controller/route:

app.put('/places/:name', function(req, res) {
var name = req.body.name;
var capital = req.body.capital;
var continent = req.body.continent;
Place.update({ name: name, capital: capital, continent: continent}, function(name) {
    res.redirect('/places/'+name)
});

});

I've tried a bunch of different ways but can't seem to get it.
Also, isn't how I declare the three {name, capital, and continent} variables blocking further operations? Thanks. General debugging help is also appreciated. Console.log(name) (right below the declaration) doesn't log anything.

Jade form:

h1 Editing #{place.name}
form(action='/places/'+place.name, method='POST')
  input(type='hidden', name='_method', value='PUT')
  p
    label(for='place_name') Name:
    p
    input(type='text', id='place_name', name='place[name]', value=place.name)
    p
    label(for='place_capital') Capital: 
    p
    input(type='text', id='place_capital', name='place[capital]', value=place.capital)
    p
    label(for='place_continent') Continent:
    p
    textarea(type='text', id='place_continent', name='place[continent]')=place.continent
    p
    input(type="submit")
Scott Stensland
  • 26,870
  • 12
  • 93
  • 104
JohnAllen
  • 7,317
  • 9
  • 41
  • 65

4 Answers4

41

You have to find the document before updating anything:

Place.findById(req.params.id, function(err, p) {
  if (!p)
    return next(new Error('Could not load Document'));
  else {
    // do your updates here
    p.modified = new Date();

    p.save(function(err) {
      if (err)
        console.log('error')
      else
        console.log('success')
    });
  }
});

works for me in production code using the same setup you have. Instead of findById you can use any other find method provided by mongoose. Just make sure you fetch the document before updating it.

schaermu
  • 13,478
  • 2
  • 39
  • 32
  • Thanks! Quick question: how does the anonymous callback function after the db.query know that 'p' in your example is/should be the query result(s)? Is that just a built-in behavior? – JohnAllen Feb 28 '11 at 02:28
  • It does not "know" it by itself. Thats why you have to check it for null (since the result is always null on an error). In my example i didn't use the `err` object, this is where the exact error message would be included. if you query the wrong members (for example `p.foo` whereas p has no foo member), you'll get `undefined`. – schaermu Feb 28 '11 at 08:08
  • 1
    @JohnAllen, IDK if this is what you're asking: findById promises to always pass the same argument list to its callback; an error and the document. Since function(err, p) calls that 2nd argument "p", then p is the document. – grantwparks Mar 18 '12 at 23:38
  • anyone know if I can use findByIdAndUpdate to find ID and update the doc with one command? – Nam Nguyen Sep 17 '13 at 18:49
  • I'm getting `ReferenceError: next is not defined` – maudulus Nov 15 '14 at 15:59
26

Now, i think you can do this :

Place.findOneAndUpdate({name:req.params.name}, req.body, function (err, place) {
  res.send(place);
});

You can find by id too :

Place.findOneAndUpdate({_id:req.params.id}, req.body, function (err, place) {
  res.send(place);
});
k33g_org
  • 530
  • 5
  • 8
5

So now you can find and update directly by id, this is for Mongoose v4

Place.findByIdAndUpdate(req.params.id, req.body, function (err, place) {
  res.send(place);
});

Just to mention, if you needs updated object then you need to pass {new: true} like

Place.findByIdAndUpdate(req.params.id, req.body, {new: true}, function (err, place) {
  res.send(place);
});
Abhishek Gupta
  • 4,066
  • 24
  • 27
0

I think your problem is that you are using node 0.4.0 - try moving to 0.2.6 with an it should work. There is an issue logged on github with the bodyDecoder not populating the req.body.variable field in node >= 0.3.0.

Chris
  • 1,241
  • 1
  • 14
  • 33