36

In MongoDB, I have a movie collection that has an array of languages , e.g.
languages: [0:USA, 1: German, 2: French, ...etc]

The array values are not in any particular order.

How can I now update an array value based on some specific value? Let's say I want to update all "French" and replace it with "Francais" for the entire collection. How can I do that?

2
  • 2
    Have you tried db.movies.updateMany({ "languages": "French" }, { "$set": { "languages.$": "Francais" } })? Refer to the documentation Commented Jan 31, 2018 at 15:26
  • thank you, this did work indeed. I didnt know about that .$ syntax.. Commented Jan 31, 2018 at 16:01

2 Answers 2

50

Use the positional $ operator which identifies the element in the languages array to update without explicitly specifying its position in the array i.e. instead of knowing the position in advance and updating the element as:

db.movies.updateMany(
    { "languages": "French" }, 
    { "$set": { "languages.2": "Francais" } }
)

you can just use the $ operator as:

db.movies.updateMany(
    { "languages": "French" }, 
    { "$set": { "languages.$": "Francais" } }
)

Alternatively using the aggregation pipeline for update operations:

db.movies.updateMany(
    { "languages": "French" }, 
    [
        { "$set": { 
            "languages": {
                "$map": {
                    "input": "$languages",
                    "in": {
                        "$cond": [
                            { "$eq": ["$$this", "French"] }, 
                            "Francais", 
                            "$$this"
                        ]
                    }
                }
            }
        } }
    ]
)
Sign up to request clarification or add additional context in comments.

Comments

14

In case you have duplicate entries in your array like this:

"languages" : [ 
    "USA", 
    "German", 
    "French",
    "French"
]

You can use the following syntax to replace all occurrences starting with MongoDB v3.5.12 (documentation)

db.movies.updateMany(
    { "languages": "French" },
    { "$set": { "languages.$[filter]": "Francais" } },
    { "arrayFilters": [ { "filter": "French" } ] }
)

Strictly speaking, the { "languages": "French" } filter is not needed. It will, however, speed up things by leveraging an index on "languages" in case there is one. If that's not needed/wanted, passing a simple {} value as the first parameter works as well.

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.