Home > Blockchain >  Add element to array if not exists, increment a value in the element if element already exists in th
Add element to array if not exists, increment a value in the element if element already exists in th

Time:04-07

The mongodb collection looks like the array below

[
  {
    "_id": 1,
    "arr": [
      {
        "key": "abc",
        "val_a": 2
      }
    ]
  },
  {
    "_id": 2
  }
]

What I want to do is increment 1 to the element in arr array with key def. If the element with key def is not in the array arr, I want to add a new element like below to arr

{
    "key": "def",
    "val_a": 1
}

I tried

db.collection.update({
  "_id": 1,
  "arr.key": "def",
  
},
{
  "$inc": {
    "arr.$.val_a": 1
  }
})

But it is not adding the new element. The result is like

[
  {
    "_id": 1,
    "arr": [
      {
        "key": "abc",
        "val_a": 2
      }
    ]
  },
  {
    "_id": 2
  }
]

What I am expecting is something like this:

[
  {
    "_id": 1,
    "arr": [
      {
        "key": "abc",
        "val_a": 2
      },
      {
        "key": "def",
        "val_a": 1
      }
    ]
  },
  {
    "_id": 2
  }
]

I want to do it in one operation as I am intending to do is a BulkWrite operation with UpdateOneModel.

CodePudding user response:

Query

  • finds the _id
  • new-member you set any document to add
  • if arr is not array make it an empty array, so concat to work later
  • check if it exists
  • if not exists, add to the end of the array
  • else map to find it and increase its val_a

PlayMongo

*this is pipeline update, to do it with 1 query, alternative way is with 2 queries, one to check if it exists, and the second to $push (if not exists) or to $set with arrayFilters.
(you would had to send 2 queries and write 3 queries, and its not atomic safe)

update(
{"_id": {"$eq": 1}},
[{"$set": {"new-member": {"key": "abc", "val_a": 1}}},
 {"$set": {"arr": {"$cond": [{"$isArray": ["$arr"]}, "$arr", []]}}},
 {"$set": 
   {"not-exists": 
     {"$eq": 
       [{"$filter": 
           {"input": "$arr",
            "cond": {"$eq": ["$$this.key", "$new-member.key"]}}},
         []]}}},
 {"$set": 
   {"arr": 
     {"$cond": 
       ["$not-exists", {"$concatArrays": ["$arr", ["$new-member"]]},
         {"$map": 
           {"input": "$arr",
            "in": 
             {"$cond": 
               [{"$eq": ["$$this.key", "$new-member.key"]},
                 {"$mergeObjects": 
                   ["$$this", {"val_a": {"$add": ["$$this.val_a", 1]}}]},
                "$$this"]}}}]}}},
 {"$unset": ["new-member", "not-exists"]}])
  • Related