Home > Software design >  How to merge object in mongodb findandmodify
How to merge object in mongodb findandmodify

Time:12-27

I have a collection like that:

{
  '_id': objectId,
  'uuid': string,
  'contexts' object -> (0:"wifi6", 1:"anydesk", _seriablizable_class:"App\\Collection\\Context")
}

actual:

{
  "_id": {
    "$oid": "6399a76340573591210b9cf3"
  },
  "uuid": "ae7470a9-af8f-4baf-9981-1581313e3923",
  "name": "text",
  "description": "text",
  "device_info": {},
  "contexts": {
    "0": "wifi6",
    "1": "4g",
    "2": "2.4"
    "_seriablizable_class": "App\\Device\\Domain\\ValueObject\\ContextCollection"
  },
  "filter_contexts": [
    "0": "wifi6",
    "1": "4g",
    "2": "2.4"
  ],
  "deleted": false,
  "created_at": {
    "$date": {
      "$numberLong": "1671014243165"
    }
  },
  "updated_at": {
    "$date": {
      "$numberLong": "1671014243166"
    }
  }
}

expected:

{
  "_id": {
    "$oid": "6399a76340573591210b9cf3"
  },
  "uuid": "ae7470a9-af8f-4baf-9981-1581313e3923",
  "name": "text",
  "description": "text",
  "device_info": {},
  "contexts": {
    "0": "wifi6",
    "1": "4g",
    "2": "2.4",
    "3": "5G"
    "_seriablizable_class": "App\\Device\\Domain\\ValueObject\\ContextCollection"
  },
  "filter_contexts": [
    "0": "wifi6",
    "1": "4g",
    "2": "2.4",
    "3": "5G"
  ],
  "deleted": false,
  "created_at": {
    "$date": {
      "$numberLong": "1671014243165"
    }
  },
  "updated_at": {
    "$date": {
      "$numberLong": "1671014243166"
    }
  }
}

I want to update all table, add new field to contexts named "5G" to any documents that that match with contexts: "wifi6". The difficult is we need to add "5G" to the right index, that depend on "$count" fields in contexts.

I try to write an update script like this, but it didn't work

db.devices.findAndModify(
{'query':{contexts:"Wifi6"},
 'update': {
   [
     '$group': {
        "_id": "$_id",
        "count": {
            "$sum": { 
                "$size": { "$objectToArray": "$contexts" }
            }
        },
        contexts: {$first:'$contexts'}
    },
    '$set': { 'contexts':
       { $mergeObjects: [ { "$count-1": "5G"}, "$contexts" ] }
    }
   ]
 }
})

What did i wrong here?

CodePudding user response:

To dynamically create a field name in an existing object, first convert the object to an array, add the new field as a object like {k:"fieldname", v:"value"}, then convert the array back to an object.

For example, after selecting the documents to be edited, these $addFields stages would add that field to the contexts object:

  {$addFields: {
      contexts: {"$objectToArray": "$contexts"}
  }},
  {$addFields: {
      contexts: {
        "$concatArrays": [
          "$contexts",
          [{
              k: {$toString: {$sum: [-1,{"$size": "$contexts"}]}},
              v: "5G"
          }]
        ]
      }
  }},
  {$addFields: {
      contexts: {"$arrayToObject": "$contexts"}
  }}

Playground

  • Related