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?

Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
Denis Dubinin
  • 257
  • 1
  • 2
  • 7

4 Answers4

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.

Community
  • 1
  • 1
Russell
  • 12,261
  • 4
  • 52
  • 75
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

Tolga Evcimen
  • 7,112
  • 11
  • 58
  • 91
Swapnil Sonawane
  • 1,445
  • 3
  • 22
  • 37
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.
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
-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.

Community
  • 1
  • 1
pablo.vix
  • 2,103
  • 2
  • 15
  • 12