Oktav
Oktav

Reputation: 2151

mongoDB $pull from subarray

Maybe this is a popular question but I didn't manage to find my solution. I have a collection with elements like the following:

_id: ObjectId("52821d6c21c495b30a000015")
structure: {
  elements: [{
    id: "non-unique-id1",
    other_data: "value"
    subs: [{
      id: 1,
      field1: "somevalue",
      field2: "other value"
    }, {
      id: 2,
      field1: "somevalue",
      field2: "other value"
    }, {
      id: 3,
      field1: "somevalue",
      field2: "other value"
    }]
  }, {
    id: "non-unique-id2",
    subs: [{
      id: 1,
      field1: "somevalue",
      field2: "other value"
    }, {
      id: 2,
      field1: "somevalue",
      field2: "other value"
    }, {
      id: 3,
      field1: "somevalue",
      field2: "other value"
    }]
  }]
}

Now I would like to remove an element from the subs subarray given it's id. I'd like the remove to happen on all element fields.

I tried the following, but even though I get no error, nothing happens:

db.objects.update({
  "_id" : ObjectId("52821d6c21c495b30a000015")
},{
  $pull: {
    "structure.elements.subs": {id: 2}
  }
})

This should have removed the 2 occurrences of the hash with id: 2

Tried $pullAll as well but I'm getting an error:

Modifier $pushAll/pullAll allowed for arrays only

Any ideas on how can I achieve my goal?

Upvotes: 2

Views: 967

Answers (2)

Anthonny
Anthonny

Reputation: 1591

You can use $, but the query will only delete 1 subs, for the two subs of your example you must run update twice. You'll need to write a script to iterate on your docs.

db.objects.update({
  "_id" : ObjectId("52821d6c21c495b30a000015"),
  "structure.elements.subs.id": 2
},{
  $pull: {
    "structure.elements.$.subs": {"id": 2}
  }
});

If your need is for a temporary administration action it's ok, but for an application performance will too bad

Sorry for my poor english :)

Upvotes: 1

JohnnyHK
JohnnyHK

Reputation: 311835

Mongo's support for updating nested arrays is pretty weak. You have to target each elements array element separately in your $pull:

db.objects.update({
  "_id" : ObjectId("52821d6c21c495b30a000015")
},{
  $pull: {
    "structure.elements.0.subs": {id: 2},
    "structure.elements.1.subs": {id: 2}
  }
})

Upvotes: 3

Related Questions