简体   繁体   中英

MongoDB: updating an array in array

I seem to be having an issue accessing the contents of an array nested within an array in a mongodb document. I have no problems accessing the first array "groups" with a query like the following...

db.orgs.update({_id: org_id, "groups._id": group_id} , {$set: {"groups.$.name": "new_name"}});

Where I run into trouble is when I try to modify properties of an element in the array "features" nested within the "group" array.

Here is what an example document looks like

     {
        "_id" : "v5y8nggzpja5Pa7YS",
        "name" : "Example",
        "display_name" : "EX1",
        "groups" : [
            {
                "_id" : "s86CbNBdqJnQ5NWaB",
                "name" : "Group1",
                "display_name" : "G1",
                "features" : [
                    {
                        _id      : "bNQ5Bs8BWqJn6CdNa"
                        type     : "blog",
                        name     : "[blog name]"
                        owner_id : "ga5YgvP5yza7pj8nS"
                    }, 
                ]
             },
         ]
     },

And this is the query I tried to use.

db.orgs.update({_id: "v5y8nggzpja5Pa7YS", "groups._id": "qBX3KDrtMeJGvZWXZ", "groups.features._id":"bNQ5Bs8BWqJn6CdNa" }, {$set: {"groups.$.features.$.name":"New Blog Name"}});

It returns with an error message:

WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 2,
        "errmsg" : "Too many positional (i.e. '$') elements found in path 'groups.$.features.$.name'"
    }
})

It seems that mongo doesn't support modifying arrays nested within arrays via the positional element?

Is there a way to modify this array without taking the entire thing out, modifying it, and then putting it back in? With multiple nesting like this is it standard practice to create a new collection? (Even though the data is only ever needed when the parent data is necessary) Should I change the document structure so that the second nested array is an object, and access it via key? (Where the key is an integer value that can act as an "_id")

groups.$.features.[KEY].name

What is considered the "correct" way to do this?

After some more research, it looks like the only way to modify the array within an array would be with some outside logic to find the index of the element I want to change. Doing this would require every change to have a find query to locate the index, and then an update query to modify the array. This doesn't seem like the best way.

Link to a 2010 JIRA case requesting multiple positional elements...

Since I will always know the ID of the feature, I have opted to revise my document structure.

     {
    "_id" : "v5y8nggzpja5Pa7YS",
    "name" : "Example",
    "display_name" : "EX1",
    "groups" : [
        {
            "_id" : "s86CbNBdqJnQ5NWaB",
            "name" : "Group1",
            "display_name" : "G1",
            "features" : {
               "1" : {
                       type     : "blog",
                       name     : "[blog name]"
                       owner_id : "ga5YgvP5yza7pj8nS"
               }, 
            }
         },
     ]
 },

With the new structure, changes can be made in the following manner:

db.orgs.update({_id: "v5y8nggzpja5Pa7YS", "groups._id": "s86CbNBdqJnQ5NWaB"}, {$set: {"groups.$.features.1.name":"Blog Test 1"}});

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