1

I have objects like in my collection:

{
   "foo": {
       "actions": [
          ...,
          "delete"
       ]
   },
   "bar": {
      "tags": ["links", ...]
   }
}

I want to remove delete value from foo.actions from all objects that contain links value in bar.tags field.

I tried to do a basic update that seems not to work:

db.foo.update({
   "bar.tags": /links/
}, {
   $pull: {
       "foo.actions": "delete"
   }
}, {
   multi: true
});

delete field is not removed since the following request doesn't return 0:

> db.foo.find({"bar.tags": /links/, "foo.actions": /delete/}).count()
786

What's the issue here? Why delete value is not removed?

2
  • 1
    This worked fine when I tried it. Commented Sep 8, 2014 at 16:48
  • @JohnnyHK tags is inside of another object. Maybe that makes the difference? Commented Sep 8, 2014 at 16:56

1 Answer 1

2

It worked for me. Maybe you're not calling the right collection. What you want to do is print the count before and after the update to see if there's a difference.

Example:

db.foo.find({"bar.tags": /links/, "foo.actions": /delete/}).count() // 4
db.foo.update({
   "bar.tags": /links/
}, {
   $pull: {
       "foo.actions": "delete"
   }
}, {
   multi: true
});
db.foo.find({"bar.tags": /links/, "foo.actions": /delete/}).count() // 0

Setup

var createObj = function(){
  var o = {
     "foo": {
         "actions": [
            "ok"
         ]
     },
     "bar": {
        "tags": ["links"]
     }
  }
  if( Math.random() < 0.5 ){
    o.foo.actions.push("delete");
    o.foo.actions.push("delete");
    o.foo.actions.push("delete");
  }
  return o;
};
use test;
db.foo.drop();
for(var i = 0; i < 10; i++){
  db.foo.insert( createObj() );
}
Sign up to request clarification or add additional context in comments.

3 Comments

It's strange that running db.foo.update({"bar.tags": "links", "foo.actions": "delete"}, {"$pull": {"foo.actions": "delete"}}, {multi: true}) worker perfectly. Anyway, thanks for great answer!
The issue appeared because I was having a field deleteImage in foo.actions. When I was counting foo.actions: /delete/ they were being caught. Can you please update your answer with this information? May be useful for future users.
You might want to use a string instead of a regular expression next time. Because /delete/ matches any word that contains delete and not just the word delete. /^delete$/ is the same as "delete".

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.