Home > Net >  Mongo pull multiple elements inside an array of object
Mongo pull multiple elements inside an array of object

Time:10-21

I'm trying to pull one or multiple objects from an array and I noticed something odd.

Let's take the following document.

{
    "_id" : UUID("f7e80c8e-6b4a-4741-95a3-2567cccf9e5f"),
    "createdAt" : ISODate("2021-07-19T17:07:28.499Z"),
    "description" : null,
    "externalLinks" : [ 
        {
            "id" : "ZV8xMjM0NQ==",
            "type" : "event"
        }, 
        {
            "id" : "cF8xMjM0NQ==",
            "type" : "planning"
        }
    ],
    "updatedAt" : ISODate("2021-07-19T17:07:28.499Z")
}

I wrote a basic query to pull one element of externalLinks which looks like

db.getCollection('Collection').update(
  {
    _id: {
      $in: [UUID("f7e80c8e-6b4a-4741-95a3-2567cccf9e5f")]
    }
  }, {
    $pull: {
      externalLinks: {
        "type": "planning",
        "id": "cF8xMjM0NQ=="
      }
    }
  })

And it's working fine. But it's getting trickier when I want to pull multiple element from the externalLinks. And I'm using the operator $in for that. And the strange behaviour is here :

db.getCollection('Collection').update(
  {
    _id: {
      $in: [UUID("f7e80c8e-6b4a-4741-95a3-2567cccf9e5f")]
    }
  }, {
    $pull: {
      externalLinks: {
        $in: [{
          "type": "planning",
          "id": "cF8xMjM0NQ=="
        }]
      }
    }
  })

And this query doesn't work. The solution is to switch both field from externalLinks and do something like :

$in: [{
  "id": "cF8xMjM0NQ==",
  "type": "planning" 
}]

I tried multiple things like : $elemMatch, $positioning but it should be possible to pull multiple externalLinks. I also tried the $and operator without success.

I could easily iterate over the externalLinks to update but it'd be too easy.

And it's tickling my brain to choose that solution.

Any help would be appreciate, thank you !

CodePudding user response:

Document fields have order, and MongoDB compares documents based on the order of the fields see here, so what field you put first matters.

After MongoDB 4.2 we can also do pipeline updates, that can be sometimes bigger, but they are much more powerful, and feels more like programming. (less declarative and pattern matching)

This doesn't mean that you need pipeline update in your case but check this way also.

Query

  • pipeline update
  • filter and keep members that the condition doesn't exist

Test code here

db.collection.update(
{_id: {$in: ["f7e80c8e-6b4a-4741-95a3-2567cccf9e5f"]}},
[{"$set": 
   {"externalLinks": 
     {"$filter": 
       {"input": "$externalLinks",
        "cond": 
        {"$not": 
         [{"$and": 
           [{"$eq": ["$$this.id", "ZV8xMjM0NQ=="]},
            {"$eq": ["$$this.type", "event"]}]}]}}}}}])
  • Related