skip to Main Content

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]

2

Answers


  1. 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

    Login or Signup to reply.
  2. 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

    *its pipeline update requires MongoDB >= 4.2

    Playmongo

    update({},
    [{"$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"}]}}}}}}}])
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search