2

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?

2 Answers 2

3

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}
  }
})
Sign up to request clarification or add additional context in comments.

1 Comment

Hmm, I was afraid of that... Unfortunately the elements array is not ordered nor fixed so I wouldn't know what indexes to target. Thanks anyway.
1

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 :)

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.