Home > Software design >  MongoDB remove element from array by index
MongoDB remove element from array by index

Time:12-15

{
  "_id": ...,
  "array": [
    {
      "identifier": a
    },
    {
      "identifier": b
    }
  ]
}

Is it currently possible to remove an element from an array by its index in MongoDB with a single query? I've been finding answers that require unset and pull, guided by the mongodb problem. however, they are all quite old. (for example, I want to delete element 0)

CodePudding user response:

There is no straight way of pulling/removing by array index. In fact, this is an open issue http://jira.mongodb.org/browse/SERVER-1014 , you may vote for it.

The workaround is using $unset and then $pull:

db.lists.update({}, {$unset : {"interests.3" : 1 }}) db.lists.update({}, {$pull : {"interests" : null}}) Update: as mentioned in some of the comments this approach is not atomic and can cause some race conditions if other clients read and/or write between the two operations. If we need the operation to be atomic, we could:

Read the document from the database Update the document and remove the item in the array Replace the document in the database. To ensure the document has not changed since we read it, we can use the update if current pattern described in the mongo docs

CodePudding user response:

As far as I know there is not a directed way to do it but you can to use another way: Using aggregation stages into update query:

The trick is to use $slice. Check how it works here.

This example is concating two arrays, each array is using a different syntax, note that the documentation says:

$slice

Returns a subset of an array.

$slice has one of two syntax forms:

The following syntax returns elements from either the start or end of the array:

{ $slice: [ <array>, <n> ] }

The following syntax returns elements from the specified position in the array:

{ $slice: [ <array>, <position>, <n> ] }

So, in this example:

  • The first $slice is getting the elements from the start to the index.
  • The second $slice is getting the elements from the index to the end.

If you concatenate these two arrays you get the same array without the index.

db.collection.update({
  "_id": 1
},
[
  {
    "$set": {
      "array": {
        "$concatArrays": [
          {
            "$slice": [
              "$array",
              YOUR_INDEX
            ]
          },
          {
            "$slice": [
              "$array",
              {
                "$add": [
                  1,
                  YOUR_INDEX
                ]
              },
              {
                "$size": "$array"
              }
            ]
          }
        ]
      }
    }
  }
])

Example here

  • Related