0

How do I update a value inside a object inside an array. I will provide the exact array number in a variable... Heres my code:

var num = 0;
var ObjectID=require('mongodb').ObjectID;

db.collection('polls').findAndModify({
    query: {_id: ObjectID(_id param)},
    update: { $inc: { total: 1, "Data.chart." + num.toString + ".value": 1} }
});

This is what I want to update

{total: 0, "Data": [ 
  { value: 0, label: 'Beatles', color: '#4169E1' },
  { value: 0, label: 'Sting', color: '#C0C0C0' },
  { value: 0, label: 'Police', color: '#FFA500' },
  { value: 0, label: 'Journey', color: '#FF4500' },
  { value: 0, label: 'Genesis', color: '#EE82EE' } 
  ]
}

2 Answers 2

1

You seem to have a subsection, chart in the query that does not exist in the actual data to update. Just eliminate that;

db.collection('polls').findAndModify({
    query: {_id: ObjectID(_id param)},
    update: { $inc: { total: 1, "Data." + num.toString + ".value": 1} }
});

turns the query into

db.polls.update({}, { $inc: { total: 1, "Data.2.value": 1} })

resulting in

db.polls.find().pretty()
{
    "_id" : ObjectId("56cbebb6ef788d178e2dfdc0"),
    "total" : 1,
    "Data" : [
        ...
        {
            "value" : 1,
            "label" : "Police",
            "color" : "#FFA500"
        },
        ...
Sign up to request clarification or add additional context in comments.

Comments

0

JavaScript "stringifies" presented keys, so this is why you are not getting what you expect.

To use a variable as part of a "calculated key name" you need to use the bracket [] notation to define the object:

var num = 0;

var update = { "$inc": { "total": 1 } };

update["$inc"]["Data." + num + ".value"] = 1;

db.collection('polls').findAndModify({
    query: { _id: ObjectID(_id param) },
    update: update
});

Better yet, you should not presume the "index" that you think you want to modify is the actual location of the data. Instead match the array element in the query and use the positional $ operator instead of a hard index:

db.collection('polls').findAndModify({
    query: { "_id": ObjectID(_idParam), "Data.label": 'Beatles'   },
    update: { "$inc": { "total": 1, "Data.$.value": 1 } }
});

So the element that matches Data.label as "Beatles" will be the one updated, and regardless of the current index position in the array.

That means "scalable", where other writes could alter the array content but you are still updating the one you want, even if it changed position due to another update.

N.B The document in your question has the path to array elements as Data and not Data.chart. But apply however your real data is contructed.

3 Comments

This way isn't working for me because I don't know the name of "Beatles" because I have multiple polls and can't search for each label individually.
@NathanO The "answer" here was about interpolating the num variable into a key for the update. The suggested and attempted "Data." + num + ".value" cannot work since it is invalid to do that in JavaScript. Only the variable construction as shown is valid. The usage of an external identifier is a "recommendation" as opposed to using the "index value" directly, and again the reasons are explained within the content of the answer. Paste both pieces of code into any JavaScript REPL. What I say will work does. Your accepted answer right now will error.
Ok, I finally got it with db.collection('polls').update({_id: ObjectID(currentPoll)}, { $inc: { total: 1, ["Data."+ voteNum +".value"]: 1} });

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.