简体   繁体   中英

Update an embedded array inside an document if it exists otherwise create a new document MongoDB NodeJS

I want to update an embedded array if the field exists otherwise make a new document with the fields specified.

tldr: I have the following update query that only updates the embedded array in the first document. For example: if the mac_address doesn't exist in the first document's embedded array 'devices', it doesn't look in the other documents.

To set/update the state of the device, I have the update query and to insert new data if it doesn't exist; I am checking the condition by if(!result.nModified) inside the update function.

When I run this code, it only looks in the first document for the mac_address if it exists, it updates... Yes it works!

If it doesn't exist -> it makes a new document. Yes it works.

Then if it is to check for the last inserted mac_address in the new document, it re-inserts it and duplicates are formed.

Update function only works on the first document and it skips the rest.

Any help would be really appreciated. I have been searching for a solution for the last week or so. Tried all the possible solutions I could; but it doesn't behave the way I want it to as specified.

mac and state are variables defined before this code:

  db.devices.update({
      'devices.mac_address': mac
    }, {
      $set: {
        'devices.$.state': state
      }
    },
    function(err, result) {
      if (err) {
        console.log('error: ' + err);
      }
      console.log('result-->' + JSON.stringify(result));

      if (!result.nModified) {
        db.devices.insert({
            name: 'undefined',
            'devices': [{
              '_id': new mongojs.ObjectID(),
              'name': 'undefined',
              'type': 'undefined',
              'state': state,
              'ip_address': ip_address,
              'mac_address': mac,
              'update_timestamp': new Date(),
              'power': [{
                'value': '22',
                'time': new Date()
              }]
            }]
          },
          function(err, result) {
            if (err) {
              console.log('error: ' + err);
            }
            console.log('result-->' + result);
          });
      }
    });

This is my JSON document.

[
   {
      "_id": "579a8116077f4a6fc78188c8",
      "name": "Bedroom",
      "devices": [
         {
            "_id": "579a82ebe3648480708be146",
            "name": "Smart Switch",
            "type": "switch",
            "state": "on",
            "ip_address": "192.168.4.22",
            "mac_address": "5c:cf:7f:03:35:ab",
            "update_timestamp": "2016-07-28T22:10:51.957Z",
            "power": [
               {
                  "value": "5000",
                  "time": "2016-07-28T22:10:51.957Z"
               }
            ]
         },
   {
      "_id": "57a2e0b1a6fdb70d35e95dfb",
      "name": "Living Room",
      "devices": [
         {
            "_id": "57a2e0b1a6fdb70d35e95dfa",
            "name": "Ceiling Fan",
            "type": "switch",
            "state": "disconnected",
            "ip_address": "142.58.184.155",
            "mac_address": "5c:cf:7f:03:35:aa",
            "update_timestamp": "2016-08-04T06:29:05.247Z",
            "power": [
               {
                  "value": "120",
                  "time": "2016-08-04T06:29:05.247Z"
               }
            ]
         }
      ]
   }
]

So I eventually ended up solving my problem and I am posting my solution for anyone that might have the similar or close to what I was experiencing.

I was using the if condition all wrong. I was checking the 'nModified' with !. I had to replace it with nModified === 0 since it returns 0 when there is nothing to update and it tells us that this is a new record.

Here is the modified and updated working code:

db.test.update({
      'devices.mac_address': mac
    }, {
      $set: {
        'devices.$.state': state,
        'devices.$.update_timestamp': new Date(),
      },
    $push: {'devices.$.power': {'value': power, 'time': new Date()}}
    }, {
      upsert: false
    },
    function(err, result) {
      if (err) {
        console.log('error: ' + err);
      }

      console.log('Updated Existing Device: ' + JSON.stringify(result));
      if (result.nModified === 0) {
        console.log('NEW DEVICE!!');

          db.test.insert({
              'room_name': 'Unassigned',
              'devices': [{
                'name': 'Unassigned',
                'type': 'Unassigned',
                'state': state,
                'ip_address': ip_address,
                'mac_address': mac,
                'update_timestamp': new Date(),
                'power': []
              }]

            },
            function(err, result) {
              if (err) {
                console.log('error: ' + err);
              }
              console.log('NEW DEVICE ADDED RESULTS: ' + JSON.stringify(result));
            });
      }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM