codephobia
codephobia

Reputation: 1590

Returning only one item of an array in mongoose?

I am trying to grab one array element and update a bunch of it's properties. Here is how I am currently doing it which feels like the wrong way to me. Can this be done without having to loop through the array to match the _id? Can you select just one of the array elements by _id to be updated?

Schemas.Users.findOne({ _id: req.session.userID })
.select('friends').exec(function(err, user){
  if (err) return next(err);

  // figure out which friend I should be updating
  var index = null;
  for (var i = 0; i < user.friends.length; i++) {
    if (user.friends[i]._id == req.params.friendID) {
      index = i;
      break;
    }
  }

  // if we didn't find the friend, something went wrong
  if (index === null) {
    console.log('Error: index not found.');
    return res.redirect('somepage');                
  }

  // update friend
  user.friends[index].name = req.body.name;

  user.markModified('friends');
  user.save();

  return res.redirect('somepage');
});

Upvotes: 0

Views: 1463

Answers (1)

Leonid Beschastny
Leonid Beschastny

Reputation: 51490

Yes, Mongoose have an id method designed especially for your case:

Schemas.Users.findOne({
  _id: req.session.userID,
}).select('friends').exec(function(err, user){
  if (err) return next(err);

  var friend = user.friends.id(req.params.friendID);

  // if we didn't find the friend, something went wrong
  if (friend === null) {
    console.log('Error: index not found.');
    return res.redirect('somepage');                
  }

  // update friend
  friend.name = req.body.name;

  user.save();

  return res.redirect('somepage');
});

If your only goal it to set the name of the user's friend, then you may consider using update instead of findOne and save:

Schemas.Users.update({
  _id: req.session.userID,
  friends: {$elemMatch: {
    _id: req.params.friendID
  }}
}, {
  'friends.$.name': req.params.friendID
}).exec(function(err, numberAffected){
  if (err) return next(err);

  // if we didn't find the friend, something went wrong
  if (numberAffected === 0) {
    console.log('Error: index not found.');
    return res.redirect('somepage');                
  }

  return res.redirect('somepage');
});

Update is faster, but Mongoose setters, validators and middlewares don't work with it.

Upvotes: 1

Related Questions