8

I have a document in a mongodb collection like this :

{
    sessions : [
        {
            issues : [ 
                {
                    id : "6e184c73-2926-46e9-a6fd-357b55986a28",
                    text : "some text"
                },   
                {
                    id : "588f4547-3169-4c39-ab94-8c77a02a1774",
                    text : "other text"
                }
            ]
        } 
    ]
} 

And I want to update the issue with the id 588f4547-3169-4c39-ab94-8c77a02a1774 in the first session.

The problem is that I only know that it's the first session and the issue id (NOT the index of the issue !)

So I try something like this :

db.mycollection.update({ "sessions.0.issues.id" : "588f4547-3169-4c39-ab94-8c77a02a1774"}, 
                       { $set: { "sessions.0.issues.$.text" : "a new text" }})

But I got the following result :

WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 16837,
        "errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: sessions.0.issues.$.text"
    }

How can I do this ?

Thanks for help.

Frédéric Guégan
  • 109
  • 1
  • 2
  • 7

1 Answers1

11

You have to use this (apparently equivalent) query:

db.mycollection.update({"sessions.0.issues": {$elemMatch: {id: <yourValue>}}}, {$set: {"sessions.0.issues.$.text": "newText"}})

Notice that your update expression was correct.

More information about $elemMatch.

Btw, MongoDB reference explicits that $ operator does not work "with queries that traverse nested arrays".

Important: $elemMatch only works with version 4 or more.

dgiugg
  • 1,294
  • 14
  • 23
  • It works ! I tried many combinations with `$elemMatch` but no one worked. Thank you – Frédéric Guégan Jun 12 '14 at 06:33
  • Hi @dgiugg What if document with given id not exists? I'm populating update() method with `upsert=True` but it doesn't help creating new document... – Desprit Sep 10 '16 at 13:35
  • 1
    @Desprit You [cannot](https://docs.mongodb.com/manual/reference/operator/update/positional/#upsert) use `$` operator with `upsert`. I recommend you to use two different queries. You also have [`$setOnInsert`](https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/) but it will run both on an new document: `$set` and then `$setOnInsert`. – dgiugg Sep 12 '16 at 08:03