Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoose update item in array by position/index

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.

like image 722
Emiel Vandenbussche Avatar asked Dec 12 '16 08:12

Emiel Vandenbussche


3 Answers

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.
like image 92
yaoxing Avatar answered Oct 20 '22 22:10

yaoxing


Try this .I hope this will work

Model.findOneAndUpdate({query},{["answer.${element index}.content:new_data"]},{new:true},(err,docs)=>{})
like image 41
SAUMITRA KUMAR Avatar answered Oct 20 '22 21:10

SAUMITRA KUMAR


Try this:

Model.findOne({ title: 'your-title' }, function (err, doc){
  doc.answer.0.votes.$inc(); // increases votes on first answer by 1
  doc.save();
});
like image 24
Divyanshu Maithani Avatar answered Oct 20 '22 20:10

Divyanshu Maithani