0

Past answers (from mid 2013 and before) don't seem to work and links to the documentation are all out of date.

Example user object:

{
    "name": "Joe Bloggs",
    "email": "[email protected]",
    "workstations" : [
                         { "number" : "10001",
                           "nickname" : "home" },
                         { "number" : "10002",
                           "nickname" : "work" },
                         { "number" : "10003",
                           "nickname" : "vacation" }
                     ]
}

How can I modify the nickname of a workstation?

I tried using $set, workstations.$ and workstations.nickname but none gave the desired results.

3 Answers 3

1

Short answer, you have to use array index. For example, you want to update the nickname of 10002: {$set:{"workstations.1.nickname":"newnickname"}}

Here is the complete example:

> db.test.update({"_id" : ObjectId("5332b7cf4761549fb7e1e72f")},{$set:{"workstations.1.nickname":"newnickname"}})
> db.test.findOne()
{
        "_id" : ObjectId("5332b7cf4761549fb7e1e72f"),
        "email" : "[email protected]",
        "name" : "Joe Bloggs",
        "workstations" : [
                {
                        "number" : "10001",
                        "nickname" : "home"
                },
                {
                        "nickname" : "newnickname",
                        "number" : "10002"
                },
                {
                        "number" : "10003",
                        "nickname" : "vacation"
                }
        ]
}
>

If you don't know the index (position of the workstations), you can update the doc using $elemMatch:

>db.test.update(
    { 
        "email": "[email protected]",
        "workstations": { "$elemMatch" { "number" : "10002" } }
    },
    {
        "$set": { "workstations.$.nickname": "newnickname2" }
    }
)
>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks will mark as answer, is there any way of getting the array index using the workstation number?
1

@naimdjon's answer would work. To generalize, you could use the $elemMatch operator in combination with the $ positional operator to update one element in the array using below query:

db.test.update({
    // Find the document where name="Joe Bloggs" and the element in the workstations array where number = "10002"
    "name": "Joe Bloggs", 
    "workstations":{$elemMatch:{"number":"10002"}}
},
{
    // Update the nickname in the element matched 
    $set:{"workstations.$.nickname":"newnickname"}
})

Note: $elemMatch is only required if you need to match more than one component in the array. If you are going to match on just the number, you could use "workstations.number":"10002"

Comments

1

As long as you know "which" entry you wish to update then the positional $ operator can be of help. But you need to update your query form:

db.collection.update(
    { 
        "email": "[email protected]",
        "workstations": { "$elemMatch" { "nickname" : "work" } }
    },
    {
        "$set": { "workstations.$.nickname": "new name" }
    }
)

So that is the general form. What you need to do here is "match" something in the array in order to get a "position" to use for the update.

Alternately, where you know the position, then you can just "specify" the position with "dot notation":

db.collection.update(
    { 
        "email": "[email protected]",
    },
    {
        "$set": { "workstations.1.nickname": "new name" }
    }
)

Which updates the second element in the array, and does not need the "matching" part in the query.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.