2

I'm trying to update the JSON field "champ_x" from 1 to 3 and for both players 1 at a time in a dynamic function:

{
    "_id": {
        "$oid": "58a3521edf127d0a0c417cda"
    },
    "room": "room_0.0940045412694186",
    "player_1": "eee",
    "player_2": "fff",
    "player_1_details": {
        "history_moves": [],
        "champions": [
            {
                "champ_1": "na"
            },
            {
                "champ_2": "na"
            },
            {
                "champ_3": "na"
            }
        ]
    },
    "player_2_details": {
        "history_moves": [],
        "champions": [
            {
                "champ_1": "na"
            },
            {
                "champ_2": "na"
            },
            {
                "champ_3": "na"
            }
        ]
    },
    "game_state": "789",
    "__v": 0
}

I've got this model:

match_schema.statics.update_champ = function(room, turn, champ_num, champ_select, callback){
    if(champ_num == "champ_1"){
        match_mongoose.update({ room: room }, { $set: { 'player_1_details.champions.0.champ_1': champ_select}})
        .exec(function(error){
            if(error){ return callback(error); }else{ return callback(null); }
        });
    }
};

This model works fine

My problem is, I'm trying to make it dynamic, in which I can just send through the function parameters the current turn(1 or 2), and the chosen position(champ_1,2, or 3).

I've tried this:

//Update Champion
match_schema.statics.update_champ = function(room, turn, champ_num, champ_select, callback){
    match_mongoose.update({ room: room }, { $set: { 'player_'+turn+'_details.champions.0.'+champ_num: champ_select}})
    .exec(function(error){
        if(error){ return callback(error); }else{ return callback(null); }
    });
};

var match_mongoose = mongoose.model('matches', match_schema, 'matches');
module.exports = match_mongoose;

But I get an error that says the "Unexpected token +" seems like concatenating the value doesn't work. Is there a way to do this?

Thanks!

Bob Lozano
  • 838
  • 2
  • 13
  • 38
  • Possible duplicate of [Nodejs Mongo insert into subdocument - dynamic fieldname](http://stackoverflow.com/questions/12184626/nodejs-mongo-insert-into-subdocument-dynamic-fieldname) – dNitro Feb 14 '17 at 22:53

1 Answers1

1

You may build the $set modifier and the match part as suggested by @dNitro :

var modifier = { $set: {} };
modifier.$set['player_' + turn + '_details.champions.$.champ_' + champ_num] = champ_select;

You will have also an issue with array index, you specify champions.0 so it will always take the first array item which won't match for champs_2 & champs_3. One solution for this is to use positional parameter $ with a match from the array :

var match = {};
match['room'] = room;
match['player_' + turn + '_details.champions.champ_' + champ_num] = { $exists: true };

The full update function is :

matchSchema.statics.update_champ = function(room, turn, champ_num, champ_select, callback) {

    var modifier = { $set: {} };
    modifier.$set['player_' + turn + '_details.champions.$.champ_' + champ_num] = champ_select;

    var match = {};
    match['room'] = room;
    match['player_' + turn + '_details.champions.champ_' + champ_num] = { $exists: true };

    this.update(match, modifier)
        .exec(function(error) {
            if (error) {
                return callback(error);
            } else {
                return callback(null);
            }
        });
};

And calling it with :

Match.update_champ("room_0.0940045412694186", 1, 1, "new_value", function(err, res) {
    if (!err) {
        console.log(err);
        return;
    }
    console.log(res);
});

You can find a full example here

Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159