qais
qais

Reputation: 1878

Rename/update a specific tag in all documents

I have these documents in a collection:

[{
    "_id" : ObjectId("57496afadc964de30a8084a1"),
    "name" : "MongoDB: The Definitive Guide",
    "tags" : [ "IT", "SQL" ]
},{
    "_id" : ObjectId("57496afadc964de30a8084a2"),
    "name" : "MongoDB Applied Design Patterns",
    "tags" : [ "SQL", "MongoDB" ]
}]

I need to rename all "SQL" tags to "NoSQL" in all documents. I can do it by first adding the new tag-name, and then removing the one that needs updating:

  db.getCollection('Book').update(
    { tags: 'SQL' },
    { '$push': { tags: 'NoSQL' } },
    { multi: true })

  db.getCollection('Book').update(
    { tags: 'SQL' },
    { '$pull': { tags: 'SQL' } },
    { multi: true })

But this requires two separate queries.

How can I achieve this with a singe statement?

Upvotes: 3

Views: 426

Answers (2)

cubbuk
cubbuk

Reputation: 7920

You can use $ operator to update a particular element in a document, and using multi option you will update all matching documents.

db.getCollection('Book').update(
{ tags: 'SQL' },
{ '$set': { "tags.$": 'NoSQL' } },
{ multi: true })

Beware that this will only update the first matched element in a document. So assuming you may have duplicate tags in a document such as {tags: ["SQL", "Java", "SQL"]}, the above query will only update the first element. You can use $addToSet rather than $push to guarantee that there won't be duplicate tags in your documents.

Upvotes: 2

Sede
Sede

Reputation: 61225

You are using the wrong operators. You need to use the $set operator and the $ positional update operator. Also you should be using updateMany() because update() is deprecated in official language drivers.

db.getCollection('Book').updateMany(
    { 'tags': 'SQL' }, 
    { '$set': { 'tags.$': 'NoSQL' } }
)

Upvotes: 4

Related Questions