Home > OS >  $addToSet array of object if object doesn't exist
$addToSet array of object if object doesn't exist

Time:12-15

I have those kind of documents:

{
  "_id": "accountId 1",
  "codes": [
    {
      "key": "advantageCode 1",
      "dateBegin": "01/02/2012",
      "dateEnd": "01/02/2013"
    },
    {
      "key": "advantageCode 2",
      "dateBegin": "01/02/2012",
      "dateEnd": "01/02/2013"
    }
  ]
}

I would like to add a code in codes if it doesn't exist. I have tried this:

bulkWrite([{updateOne: {
            filter: { _id: commands[0].accountId },
            update: {$addToSet: {codes: {key: commands[0].advantageCode, dateBegin: commands[0].dateBegin, dateEnd: commands[0].dateEnd}}},
            upsert: true
}}])

My problem is that the object is always added into the set, even if the key property already exists. It is normal (because it is another reference), but I would like to know how to rebase the $addToSet to the key of the objects.

I need the request to be a bulkwrite, because i gather many different requests.

CodePudding user response:

Using update/aggregation ( since 4.2 ) you can do something even better:

 db.collection.update({
  "_id": "accountId 1"
 },
 [
 {
  $set: {
  codes: {
    $cond: [
      {
        $in: [
          "advantageCode 2",
          "$codes.key"
        ]
      },
      {
        $map: {
          input: "$codes",
          in: {
            $mergeObjects: [
              "$$this",
              {
                $cond: [
                  {
                    $eq: [
                      "$$this.key",
                      "advantageCode 2"
                    ]
                  },
                  {
                    "dateBegin": "01/02/2020",
                    "dateEnd": "01/02/2021"
                  },
                  {}
                ]
              }
            ]
          }
        }
      },
      {
        $concatArrays: [
          "$codes",
          [
            {
              "key": "advantageCode 2",
              "dateBegin": "01/02/2022",
              "dateEnd": "01/02/2023"
            }
          ]
        ]
      }
    ]
  }
 }
 }
])

Explained:

Update dateBegin and dateEnd for codes.key that matches , or if there is no match add the new codes object to the set.

Playground

Afcourse , if you only want to $addToSet if key is missing then you can do:

Playground2

The bulkWrite operation will look something like this:

bulkWrite([{updateOne: {
 filter: { _id: commands[0].accountId },
 update: [{ $set: { codes: { $cond: [ { $in: [commands[0].advantageCode,"$codes.key"]},{ $map: { input: "$codes",in: { $mergeObjects: [ "$$this", {}]}}},{$concatArrays: ["$codes",[{
        "key": commands[0].advantageCode , 
        "dateBegin": commands[0].dateBegin,
        "dateEnd": commands[0].dateEnd
          }
          ]
        ]
      }
    ]
   }
  }
 }
 ]
 }}])

If you need to upsert document in case accountId is not found here is the option:

 db.collection.update({
 "_id": "accountId 2"
 },
 [
 {
  $set: {
  codes: {
    "$cond": [
      {
        $ne: [
          {
            $type: "$codes"
          },
          "missing"
        ]
      },
      {
        $cond: [
          {
            $in: [
              "advantageCode 3",
              "$codes.key"
            ]
          },
          {
            $map: {
              input: "$codes",
              in: {
                $mergeObjects: [
                  "$$this",
                  {}
                ]
              }
            }
          },
          {
            $concatArrays: [
              "$codes",
              [
                {
                  "key": "advantageCode 3",
                  "dateBegin": "01/02/2022",
                  "dateEnd": "01/02/2023"
                }
              ]
            ]
          }
        ]
      },
      {
        "key": "advantageCode 3",
        "dateBegin": "01/02/2022",
        "dateEnd": "01/02/2023"
      }
    ]
    }
   }
  }
  ],
  {
   upsert: true
 })

Explained:

  1. In case accountId is not found insert new document.
  2. In case codes.key is not found insert new object with the new key to the codes array.

Playground3

  • Related