6

I have the following object in my mongo database named music.

I want to update where the genre is Grunge
The band name is Nirvana
The album name is Nevermind
The track order is 1

and change the track's name to "Smells Like Teen Spirit!".
I've tried playing with the positional operator, but can't quite figure this out.

{
    genre : "Grunge",
    bands : [ {
        name : "Nirvana",
        albums : [ {
            name : "Nevermind",
            tracks : [ {
                name : "Smell Like Teen Spirit",
                order : 1,
                duration : 301
            },
            {
                name : "In Bloom",
                order : 2,
                duration : 254                                                  
            } ]
        },
        {
            name : "In Utero",
            tracks : [ {
                name : "Server the Servants",
                order : 1,
                duration : 216
            },
            {
                name : "Scentless Apprentice",
                order : 2,
                duration : 254                                                  
            } ]
        } ]
    },
    {
        name : "Karma++ : A Nirvina Tribute Band",
        albums : [ {
            name : "Nevermind",
            tracks : [ {
                name : "Smell Like Teen Spirit",
                order : 1,
                duration : 301
            },
            {
                name : "In Bloom",
                order : 2,
                duration : 254                                                  
            } ]
        },
        {
            name : "In Utero",
            tracks : [ {
                name : "Server the Servants",
                order : 1,
                duration : 216
            },
            {
                name : "Scentless Apprentice",
                order : 2,
                duration : 254                                                  
            } ]
        } ]
    } ]
}
2
  • Have you considered changing your DB design a bit? Would perhaps make more sense if your document was a 'band' with a 'genre' attribute - and would make this particular query a lot easier too. Commented Apr 26, 2012 at 21:35
  • This was just the quickest example I could think of. If I were to actually do a 'music' database, I'd probably set songs as the root element with artists, albums, and genres as arrays; allowing for things like David Bowie / Queen's 'Under Pressure' (2 artists, multiple albums). Commented Apr 26, 2012 at 22:04

1 Answer 1

10

Unfortunately, at present it is only possible to use a single "$" positional per update. This limits the update to a single embedded array, similar to the example in the documentation: http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator (From your post, it looks like you have already found this, but I have included the link for the benefit of any other users reading this post.)

In order to make the update, you will have to know the position of two out of the following three: The position of the band in the "bands" array, the position of the album in the albums array, or the position of the track in the "tracks" array.

There is a feature request for this functionality, and it is slated for version 2.3.0 (although this is subject to change).
https://jira.mongodb.org/browse/SERVER-831 "Positional Operator Matching Nested Arrays"

For the time being, you will have to know the position of the sub documents in two out of the three arrays:

db.music.update({genre : "Grunge", "bands.name" : "Nirvana"}, {$set:{"bands.$.albums.0.tracks.0.name":"Smells Like Teen Spirit!"}})

db.music.update({genre : "Grunge", "bands.0.albums.name" : "Nevermind"}, {$set:{"bands.0.albums.$.tracks.0.name":"Smells Like Teen Spirit!"}})

or

db.music.update({genre : "Grunge", "bands.0.albums.0.tracks.order" : 1}, {$set:{"bands.0.albums.0.tracks.$.name":"Smells Like Teen Spirit!"}})
Sign up to request clarification or add additional context in comments.

2 Comments

Seems they broke backward compatibility in version 2.6.x. I get "The positional operator did not find the match needed from the query" for your second example (mongodb 2.6.4). it works fine in older versions.
It's a bug and they approve it, this answer is no longer valid in mongoDB 2.6 jira.mongodb.org/browse/SERVER-14886

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.