简体   繁体   中英

Update selected elements of array in mongoDB object

I have document like this,

{
    "_id": {
        "$oid": "5f33aca82b2fcf5324290ae1"
    },
    "active": true,
    "addresses": [
        {
            "country": "IN",
            "formatted": "xyz",
            "locality": "San Francisco",
            "postalCode": "7656",
            "primary": true,
            "region": "CA",
            "streetAddress": "abc",
            "type": "work"
        },
        {
            "country": "US",
            "formatted": "xyz",
            "locality": "fdfdf",
            "postalCode": "91608",
            "primary": true,
            "region": "CA",
            "streetAddress": "def",
            "type": "other"
        }
    ]
}

The address attribute is multivalued , i want to update "streetAddress" of all address entries where "type"=="work".

But when i try this query below, "streetAddress" of all entries are getting updated.

mongo.db.test.update_one({'_id': ObjectId('5f33aca82b2fcf5324290ae1'), 'addresses.type':'work'}, {"$set":{'addresses.$[].streetAddress': "mno"}},upsert=True)

the result is,

{
    "_id": {
        "$oid": "5f33aca82b2fcf5324290ae1"
    },
    "active": true,
    "addresses": [
        {
            "country": "IN",
            "formatted": "xyz",
            "locality": "San Francisco",
            "postalCode": "7656",
            "primary": true,
            "region": "CA",
            "streetAddress": "mno",
            "type": "work"
        },
        {
            "country": "US",
            "formatted": "xyz",
            "locality": "fdfdf",
            "postalCode": "91608",
            "primary": true,
            "region": "CA",
            "streetAddress": "mno",
            "type": "other"
        }
    ]
}

as you can see both entries are getting modified.

I am using flask-pymongo library.

$[] will update elements of the arrays

But $[<identifier>] will update only elements that match the filter

You can read more here

I think something like this should work :

mongo.db.test.update_one({'_id': ObjectId('5f33aca82b2fcf5324290ae1')}, 
{"$set":{'addresses.$[addr].streetAddress': "mno"}},
{arrayFilters: [ { "elem.type": 'work' } ]},
upsert=True)
Actual working code on widows 10 Mongo client
//data prep before:
db.test12.insert({
    "active": true,
    "addresses": [
        {
            "country": "IN",
            "formatted": "xyz",
            "locality": "San Francisco",
            "postalCode": "7656",
            "primary": true,
            "region": "CA",
            "streetAddress": "mno",
            "type": "work"
        },
        {
            "country": "US",
            "formatted": "xyz",
            "locality": "fdfdf",
            "postalCode": "91608",
            "primary": true,
            "region": "CA",
            "streetAddress": "mno",
            "type": "other"
        }
    ]
});

--
//data changes post update, you need to use $ to access array elements in the address array
> db.test12.updateOne({"addresses.type":"work"},{$set:{"addresses.$.streetAddress":"St Johns road"}});
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.test12.find().pretty();
{
        "_id" : ObjectId("5f492467e551d4c998f3c9ca"),
        "active" : true,
        "addresses" : [
                {
                        "country" : "IN",
                        "formatted" : "xyz",
                        "locality" : "San Francisco",
                        "postalCode" : "7656",
                        "primary" : true,
                        "region" : "CA",
                        "streetAddress" : "St Johns road",
                        "type" : "work"
                },
                {
                        "country" : "US",
                        "formatted" : "xyz",
                        "locality" : "fdfdf",
                        "postalCode" : "91608",
                        "primary" : true,
                        "region" : "CA",
                        "streetAddress" : "mno",
                        "type" : "other"
                }
        ]
}
>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM