Home > Enterprise >  Remove only one of the selected elements from the array in mongodb
Remove only one of the selected elements from the array in mongodb

Time:08-10

I have an array that is like [1,2,1,2,3,5,2]. And I want to remove only one element amongst the selected elements. I used $pull operator and it doesn't work as I required, it remove all elements I specified.

db.user.updateOne({_id: ...}, {$pull:{'array': 1}})

I tried it and give this result: [2,2,3,5,2].

is there any way to get the result: [2,1,2,3,5,2]

CodePudding user response:

This feature does not exist (and won't), as you can see in this Jira. ticket they choose they won't do this.

Here is a hacky work around - the strategy will be to find the index of the first matching element and slice it out of the array, like so:

db.collection.update({},
[
  {
    "$set": {
      "array": {
        "$concatArrays": [
          {
            $cond: [
              {
                $gt: [
                  {
                    "$indexOfArray": [
                      "$array",
                      1
                    ]
                  },
                  0
                ]
              },
              {
                "$slice": [
                  "$array",
                  0,
                  {
                    "$indexOfArray": [
                      "$array",
                      1
                    ]
                  }
                ]
              },
              []
            ]
          },
          {
            "$slice": [
              "$array",
              {
                "$add": [
                  {
                    "$indexOfArray": [
                      "$array",
                      1
                    ]
                  },
                  1
                ]
              },
              {
                "$size": "$array"
              }
            ]
          }
        ]
      }
    }
  }
])

Mongo Playground

CodePudding user response:

Query

  • $reduce the array starting with {"n-ar": [], "found": false}
  • the first time you find it you ignore it, and you set found=true
  • else you just $concat to add the member to the new-ar

*it can be generalized, like remove the first 4 occurences, if integer is used as found

Playmongo

aggregate(
[{"$set": 
   {"ar": 
     {"$getField": 
       {"field": "n-ar",
        "input": 
         {"$reduce": 
           {"input": "$ar",
            "initialValue": {"n-ar": [], "found": false},
            "in": 
             {"$cond": 
               [{"$and": 
                   [{"$eq": ["$$this", 1]}, {"$eq": ["$$value.found", false]}]},
                 {"n-ar": "$$value.n-ar", "found": true},
                 {"n-ar": {"$concatArrays": ["$$value.n-ar", ["$$this"]]},
                  "found": "$$value.found"}]}}}}}}}])
  • Related