5

Is there a way to update for example the second item in an array with mongoose?

Schema:

title: String,
answer: [{
    content: String,
    votes: Number
}]

In my case I want to update the first or second answer, so it has 1 vote more.

Emiel Vandenbussche
  • 363
  • 1
  • 5
  • 12

3 Answers3

7

I'm not a mongoose expert. But there seems to be some answer you can reference.
So the short answer is yes, you can update an array element by specify its index. In shell it would be:

db.collection.update({...}, {$inc: {"answer.0.votes": 1}})

where 0 is the index of element you want to update. I'm sure you can find corresponding grammar how to write this in mongoose.

In my opinion, to update an array by its index is not really a good idea. What if an element is removed/inserted? Your embedded array element is like a one to many relation in a RDBMS. They should have unique identifier like an ObjectId to be located more easily. Suggested data structure:

{
    title: "This is a question",
    answer: [{
        id: ObjectId("584e6c496c9b4252733ea6fb"),
        content: "Answer",
        votes: 0
    }]
}

And query by id to find the exact answer you are voting up:

db.collection.update({"answer": {$elemMatch: {id: ObjectId("584e6c496c9b4252733ea6fb")}}}, {$inc: {"answer.$.votes": 1}});

where $ means the matched element in the array.

edit - 2018-04-03

  1. if there's only one condition, $elemMatch is not necessary. It's meant for matching 2 or more conditions in one element. Without $elemMatch, different conditions may match different element in the array. Which is not expected in most scenarios.
  2. As of 3.6 MongoDB introduced $[], which allows you to update all elements in an array in one update.
yaoxing
  • 4,003
  • 2
  • 21
  • 30
  • 1
    I edited your answer a bit so i can pass a variable: var incObject = {}; incObject['options.'+myIndex+'.votes'] = 1; db.collection.update({...}, {$inc: incObject}) – Emiel Vandenbussche Dec 12 '16 at 10:45
2

Try this .I hope this will work

Model.findOneAndUpdate({query},{["answer.${element index}.content:new_data"]},{new:true},(err,docs)=>{})
SAUMITRA KUMAR
  • 697
  • 6
  • 7
1

Try this:

Model.findOne({ title: 'your-title' }, function (err, doc){
  doc.answer.0.votes.$inc(); // increases votes on first answer by 1
  doc.save();
});
Divyanshu Maithani
  • 13,908
  • 2
  • 36
  • 47