19

For example I have this document:

db.test.save({
  _id: 1,
  list: [
    { key: "a" },
    { key: "b" },
    { key: "c" },
    { key: "d" },
    { key: "e" }
  ]
})

and I need remove to the second element from the list.

For now I do that in two steps. I first unset the second list element but the $unset operator doesn't remove the element, it modifies it to null, and after that I pull any nullable value from the list field:

db.test.update({_id: 1}, {$unset: {"list.2": 1}})
db.test.update({_id: 1}, {$pull: {list: null}})

Is there a solution to do that in one operation?

4 Answers 4

8

No, unfortunately what you are doing is currently the best option. Have a look at this question: In mongoDb, how do you remove an array element by its index which links to a Jira for this very issue.

Sign up to request clarification or add additional context in comments.

Comments

3

if you know the value which you want to remove

db.test.update({{_id: 1},{"$pull" : {"list" : { "key" : "c"}}},false,false)

more info at

http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanArray

2 Comments

Is it possible to use this with findAndModify where the id of the document and the existence of the array item are used as the query arguments?
Why you use ¿"false,false"? Thank you! very useful!
0

Starting in Mongo 4.4, the $function aggregation operator allows applying a custom javascript function to implement behaviour not supported by the MongoDB Query Language.

For instance, in order to update an array by removing an element at a given index:

// {
//   "_id" : 1,
//   "list" : [
//     { "key" : "a" },
//     { "key" : "b" },
//     { "key" : "c" },
//     { "key" : "d" },
//     { "key" : "e" }
//   ]
// }
db.collection.aggregate(
  { $set:
    { "list":
      { $function: {
          body: function(list) { list.splice(2, 1); return list; },
          args: ["$list"],
          lang: "js"
      }}
    }
  }
)
// {
//   "_id" : 1,
//   "list" : [
//     { "key" : "a" },
//     { "key" : "b" },
//     { "key" : "d" },
//     { "key" : "e" }
//   ]
// }

$function takes 3 parameters:

  • body, which is the function to apply, whose parameter is the array to modify. The function here simply consists in using splice to remove 1 element at index 2.
  • args, which contains the fields from the record that the body function takes as parameter. In our case "$list".
  • lang, which is the language in which the body function is written. Only js is currently available.

Comments

-1

Not at the current time. As it was answered in There is no straight way of pulling/removing by array index.

There is an open issue asking for that operation, even though this workaround is ok, notwithstanding it is not an atomic solution.

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.