0

Collection:

post:
  title: 'Help'
  tags: ['mongodb','foo']

Elements of the tags array are unique. I want to change all foo tags in the collection to bar tags. Can I $set an element inside an array in one step, or do I have to remove the foos from all tags arrays and add bars?

Loren
  • 13,903
  • 8
  • 48
  • 79

2 Answers2

1

Try this query:

db.posts.update({ tags: "foo" }, { $set: { "tags.$": "bar" } }, { multi: true});

But if your tags array contains more than one foo value, this query will replace only one of them.

Shad
  • 4,423
  • 3
  • 36
  • 37
  • So to achieve what OP needs he need to run N+1 commands against the server if the number of elements is N – Salvador Dali Nov 26 '13 at 01:03
  • Yes, it's true, if there are N `foo` values in one `tags` array. But as far as I understand, OP wants to update all collection of posts rather than certain array. – Shad Nov 26 '13 at 01:12
1

You can not do this at the moment with one query. One reasonable way to achieve this would have been to use $pull and $push like this:

db.a.update({
    tags : 'foo'
  },{
    $pull : {tags : 'foo'},
    $push : {tags : 'bar'}
  },{
    multi : true
})

But this would end up with Field name duplication not allowed with modifiers error message which is basically tells you that you can not use $pull and $push at the same time. Jira ticket was filed few years ago, but still it is unresolved (and based on Minor label here it is highly unlikely to be resolved soon).

One way to go with it is to run a query to find IDs of the documents that has foo, then another query to remove all these foo and another one to insert bars for all IDs. I know that potentially in between of these updates something can modify the collection, but this is one option.

Another way is to iterate through all the elements which has tags as foo and to modify them in foreach statement.

Community
  • 1
  • 1
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753