5

I'm using array of Strings to save emails:

var user = new Schema({
  // other fields...

  emails: [String]
});

Have troubles updating this field. Say, email1 and email2 are values I receive from the view:
This works well:

user.emails = [email1, email2];
user.save();
// fields are updated, all good

And this doesn't:

user.emails[0] = email1;
user.emails[1] = email2;
user.save(function(err, savedUser) {
  console.log(savedUser.emails); // updated array [email1, email2]
  // but if I retrieve now the user, the 'emails' field will not have above changes.
});

But, strangely, this works:

user.emails = [email1];
user.emails[1] = email2;
user.save();
// user.emails == [email1, email2];

Can anybody explain why this is happening?

1 Answer 1

14

It's not well documented, but when manipulating array fields you need to make sure that you're triggering Mongoose's field change detection so that it knows that the array has been modified and needs to be saved.

Directly setting an array element via its index in square brackets doesn't mark it modified so you have to manually flag it using markModified:

user.emails[0] = email1;
user.markModified('emails');

Or you can do it in one go, using the set method of the Mongoose array:

user.emails.set(0, email1);

Overwriting the entire array field also triggers it which is why this works for you:

user.emails = [email1, email2];

as well as:

user.emails = [email1];
user.emails[1] = email2;

Which means that this also works:

user.emails = [];
user.emails[0] = email1;
user.emails[1] = email2;
Sign up to request clarification or add additional context in comments.

4 Comments

Many thanks!!! Do you know how could it work in my tests w/o triggering field change detection?
@eagor Which case is unexpectedly working in your tests?
setting elements individually (user.emails[0] = email1...). Had no effect in 'dev' environment, but worked well in 'test' (array of newly retrieved object was updated)
it would be great to add note about using functions like push and splice

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.