ThomasReggi
ThomasReggi

Reputation: 59345

Update array object based on id?

I'm having a bit of a mongo issue. I was wondering if there was a way to do the following in a mongo console command rather then multiple find and update calls.

{
    "_id" : ObjectId("50b429ba0e27b508d854483e"),
    "array" : [
        {
            "id" : "1",
            "letter" : "a"
        },
        {
            "id" : "2",
            "letter" : "b"
        }
    ],
    "tester" : "tom"
}

I want to update the object with this new array item

{
    "id": "2",
    "letter": "c"
}

I used this, addToSet is limited, it won't insert an item into the array if it is already there but it will not update an item based on an identifier. In this case I would really like to update this entry based on the id.

db.soup.update({
     "tester": "tom"
 }, {
     $addToSet: {
         "array": {
             "id": "2",
             "letter": "c"
         }
     }
});

This gives me:

{
    "_id" : ObjectId("50b429ba0e27b508d854483e"),
    "array" : [
        {
            "id" : "1",
            "letter" : "a"
        },
        {
            "id" : "2",
            "letter" : "b"
        },
        {
            "id" : "2",
            "letter" : "c"
        }
    ],
    "tester" : "tom"
}

When what I really wanted was:

{
    "_id" : ObjectId("50b429ba0e27b508d854483e"),
    "array" : [
        {
            "id" : "1",
            "letter" : "a"
        },
        {
            "id" : "2",
            "letter" : "c"
        }
    ],
    "tester" : "tom"
}

Upvotes: 3

Views: 537

Answers (2)

ddoxey
ddoxey

Reputation: 2063

Here you go:

> db.collection.insert( { array : [ { id : 1, letter : 'a' }, { id : 2, letter : 'b' } ], tester : 'tom' } );
> db.collection.findOne();
{
    "_id" : ObjectId("50b431a69a0358d590a2f5f0"),
    "array" : [
        {
            "id" : 1,
            "letter" : "a"
        },
        {
            "id" : 2,
            "letter" : "b"
        }
    ],
    "tester" : "tom"
}
> db.collection.update( { tester : 'tom' }, { $set : { 'array.1' : { id : 2, letter : 'c' } } }, false, true );
> db.collection.findOne();
{
    "_id" : ObjectId("50b431a69a0358d590a2f5f0"),
    "array" : [
        {
            "id" : 1,
            "letter" : "a"
        },
        {
            "id" : 2,
            "letter" : "c"
        }
    ],
    "tester" : "tom"
}

The trick lies in the false, true, false. That is: true for upsert, false for update multiple.

For more details check out: http://www.mongodb.org/display/DOCS/Updating#Updating-update%28%29

Upvotes: 0

JohnnyHK
JohnnyHK

Reputation: 311835

You can use the $ positional operator to do this:

db.soup.update(
    {_id: ObjectId("50b429ba0e27b508d854483e"), 'array.id': '2'}, 
    {$set: {'array.$.letter': 'c'}})

The $ in the update object acts as a placeholder for the first element of array to match the query selector.

Upvotes: 7

Related Questions