如何查询同级节点的现有子级并对其进行循环以检测其是否存在? [英] How to query the existing children of a sibling node and loop over them to detect if it exists?

查看:76
本文介绍了如何查询同级节点的现有子级并对其进行循环以检测其是否存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Firebase数据库上更新(添加)新的子级.在这种情况下,我将更新两个节点and_"door/{MACaddress_1}/ins" _& _"doors/{MACaddress_2}/ins" _,这两个节点都需要通过Google Cloud函数写入名为"rooms/{roomPushKey}/ins" 的兄弟节点.

我将通过具有唯一MAC地址的IoT设备上的Arduino程序更新初始的门" 节点,该MAC地址将数据库连接到'/doors/'+ {MAC地址} +'/ins'.

这些是必不可少的条件:

1)如果尚未创建"rooms/{roomPushKey}/ins" ,请创建它(防止在写入第一个数据时出现未定义或空错误的情况).

2)两个门" 通常具有不同的子键.因此,我不能简单地覆盖同级房间" 节点的数据,因为这将删除未更新的一扇门的节点.在这里,我需要确保房间/{roomPushKey}/ins" 仅从每个中获取新数据.

3)我需要检测写入的新数据是否在同级的"rooms/{roomPushKey}/ins" 节点上不存在,因为有时两个 * doors * 将具有相同的键,并且在发生这种情况时,云功能需要在要写入的第二个键上添加后缀"_a".

这是我最初的数据结构.

root: { 
  doors: {
    111111111111: {
       MACaddress: "111111111111",
       inRoom: "-LBMH_8KHf_N9CvLqhzU", // I will need this value for the clone's path
       ins: {
          // I am creating several "key: pair"s here, something like:
          1525104151100: true,
          1525104151183: true,
          1525104150000: true // Trouble! this key is also on the other door
       }
    },
    222222222222: {
       MACaddress: "222222222222",
       inRoom: "-LBMH_8KHf_N9CvLqhzU", // I will need this value for the clone's path
       ins: {
          // I am creating several "key: pair"s here, something like:
          1525104151220: true,
          1525104151440: true,
          1525104150000: true // Trouble! this key is also on the other door
       }
    }
  },
  rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {
        // I want the function to clone the same data here:
        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true, // this key is on both doors 
        1525104150000_a: true, // so a suffix must be added 
      }
    }
  }

上周,我从雷诺·塔内克(Renaud Tarnec)获得了很多帮助,但我认为我的问题表达得不够好.

这是Google Cloud函数的当前状态:

// UPDATING ROOMS INS/OUTS

let insAfter;
let roomPushKey ;
exports.updateRoomIns = functions.database.ref('/doors/{MACaddress}').onWrite((change, context) => {
    const afterData = change.after.val(); // data after the write
    roomPushKey = afterData.inRoom;
    insAfter = afterData.ins;
    return admin.database().ref('/rooms/' + roomPushKey).once('value').then(snapshot => {
        const insBefore = snapshot.val().ins; // defining an object in the Rooms/{roomPushKey}/ins node to check what data is already there

        const updates = {}; // defining an empty updates object to populate depending on the scenario
        // avoiding the null/undefined error the first time data is written: all good here!
        if (insBefore === null || insBefore === undefined ) { 
            Object.keys(insAfter).forEach(key => {
            updates['/rooms/' + roomPushKey + '/ins/' + key] = true;
            });
        } else {
            // problem!
            Object.keys(insAfter).forEach(key => {
            if (insBefore.hasOwnProperty(key)) {
                updates['/rooms/' + roomPushKey + '/ins/' + key + '_a'] = true; 
            } else {
                updates['/rooms/' + roomPushKey + '/ins/' + key] = true;
            }
            });
        }
        return admin.database().ref().update(updates);
    });
});

这将克隆数据库中已经存在的所有数据(不是最新新键:对). 例如,如果将诸如"1999999999999:true" 之类的"key:pair"添加到这样的数据库中:

rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {

        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
      }
    }
  }

我最后得到的是一个"rooms/{roomPushKey}/ins" ,如下所示:

rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {
        // I want the function to clone the same data here:
        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
        1525104151100_a: true,
        1525104151183_a: true,
        1525104151220_a: true,
        1525104151440_a: true,
        1525104150000_a: true, 
        1999999999999: true // this last one isn't cloned but all the previous data in the database is
      }
    }
  }

何时应写成这样:

  rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {

        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
        1999999999999: true
      }
    }
  }

然后,如果另一扇门写为"1999999999999:true",则应仅将"_a"添加到最后一个节点:

  rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {

        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
        1999999999999: true,
        1999999999999_a: true,

      }
    }
  }

我需要克隆添加到"doors/{MACaddress}/ins" if 中的最后一个"key:pair" em> last"key:pair"已经在_"rooms/{roomPushKey}/ins" _ 节点中,并且忽略了所有在"doors/{ MACaddress}/ins"节点.

类似这样的东西:

有什么想法吗?

解决方案

这个问题起源于两种不同的方法.请在这里找到它们:

1)通过"rooms/{roomPushKey}/ins".

I will be updating the initial "doors" nodes through an Arduino program on a IoT device with a unique MAC Address that is connecting to the database to the '/doors/' + {MAC Address} + '/ins'.

These are the essential conditions:

1) If the "rooms/{roomPushKey}/ins" is not created yet, then create it (preventing an undefined or null error scenario when the first data is written).

2) Both "doors" normally have different child keys. So I can't simply overwrite the data of the sibling "room" node because that would delete the nodes of the one door that wasn't being updated. Here I need to make sure the "rooms/{roomPushKey}/ins" only gets the new data from each of the doors.

3) I need detect if that new data written doesn't exist already on the sibling "rooms/{roomPushKey}/ins" node because sometimes both *doors* will have the same key, and when that happens the cloud function needs to add a suffix "_a" to the second key being written.

Lets say this my initial data structure.

root: { 
  doors: {
    111111111111: {
       MACaddress: "111111111111",
       inRoom: "-LBMH_8KHf_N9CvLqhzU", // I will need this value for the clone's path
       ins: {
          // I am creating several "key: pair"s here, something like:
          1525104151100: true,
          1525104151183: true,
          1525104150000: true // Trouble! this key is also on the other door
       }
    },
    222222222222: {
       MACaddress: "222222222222",
       inRoom: "-LBMH_8KHf_N9CvLqhzU", // I will need this value for the clone's path
       ins: {
          // I am creating several "key: pair"s here, something like:
          1525104151220: true,
          1525104151440: true,
          1525104150000: true // Trouble! this key is also on the other door
       }
    }
  },
  rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {
        // I want the function to clone the same data here:
        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true, // this key is on both doors 
        1525104150000_a: true, // so a suffix must be added 
      }
    }
  }

I got a lot of help from Renaud Tarnec last week but I don't think I phrased my question well enough.

So this is the current state of the Google Cloud function:

// UPDATING ROOMS INS/OUTS

let insAfter;
let roomPushKey ;
exports.updateRoomIns = functions.database.ref('/doors/{MACaddress}').onWrite((change, context) => {
    const afterData = change.after.val(); // data after the write
    roomPushKey = afterData.inRoom;
    insAfter = afterData.ins;
    return admin.database().ref('/rooms/' + roomPushKey).once('value').then(snapshot => {
        const insBefore = snapshot.val().ins; // defining an object in the Rooms/{roomPushKey}/ins node to check what data is already there

        const updates = {}; // defining an empty updates object to populate depending on the scenario
        // avoiding the null/undefined error the first time data is written: all good here!
        if (insBefore === null || insBefore === undefined ) { 
            Object.keys(insAfter).forEach(key => {
            updates['/rooms/' + roomPushKey + '/ins/' + key] = true;
            });
        } else {
            // problem!
            Object.keys(insAfter).forEach(key => {
            if (insBefore.hasOwnProperty(key)) {
                updates['/rooms/' + roomPushKey + '/ins/' + key + '_a'] = true; 
            } else {
                updates['/rooms/' + roomPushKey + '/ins/' + key] = true;
            }
            });
        }
        return admin.database().ref().update(updates);
    });
});

This is cloning all the data that was already present in the database (not the most recent new key:pair). Example, if add a "key:pair" in such as "1999999999999: true" to a database like this:

rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {

        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
      }
    }
  }

I am ending up with a "rooms/{roomPushKey}/ins" that looks like this:

rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {
        // I want the function to clone the same data here:
        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
        1525104151100_a: true,
        1525104151183_a: true,
        1525104151220_a: true,
        1525104151440_a: true,
        1525104150000_a: true, 
        1999999999999: true // this last one isn't cloned but all the previous data in the database is
      }
    }
  }

When it should write this:

  rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {

        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
        1999999999999: true
      }
    }
  }

And then if the other door writes "1999999999999: true" it should only add the "_a" to the this last node:

  rooms: {
    -LBMH_8KHf_N9CvLqhzU: {
      ins: {

        1525104151100: true,
        1525104151183: true,
        1525104151220: true,
        1525104151440: true,
        1525104150000: true,
        1999999999999: true,
        1999999999999_a: true,

      }
    }
  }

I need to clone the last "key:pair" added to the "doors/{MACaddress}/ins" if that last "key:pair" is already in the _"rooms/{roomPushKey}/ins"_ node, and neglect all the "key:pairs" that were already in both "doors/{MACaddress}/ins" nodes.

Something like this:

Any thoughts?

解决方案

This question originated two different approaches. Please find them here:

1) By Renaud Tarnec using the Cloud Function

This should work, but I haven't test it. You may need to test is insBefore is undefined in addition to testing it is null. I let you fine tune it.

let insAfter;
let roomPushKey ;
exports.updateRoomIns = functions.database.ref('/doors/{MACaddress}').onWrite((change, context) => {
    const afterData = change.after.val(); // data after the write
    roomPushKey = afterData.inRoom;
    insAfter = afterData.ins;
    return admin.database().ref('/rooms/' + roomPushKey).once('value').then(snapshot => {
    const insBefore = snapshot.val().ins;
    const updates = {};
    if (insBefore === null || insBefore === undefined ) {
        Object.keys(insAfter).forEach(key => {
           updates['/rooms/' + roomPushKey + '/ins/' + key] = true;
        });
    } else {
        Object.keys(insAfter).forEach(key => {
           if (insBefore.hasOwnProperty(key)) {
              updates['/rooms/' + roomPushKey + '/ins/' + key + '_a'] = true; 
           } else {
              updates['/rooms/' + roomPushKey + '/ins/' + key] = true;
           }
        });
    }
    return admin.database().ref().update(updates);
    });
});.catch(error => {
    console.log(error);
    //+ other error treatment if necessary

});

2) the second approach was a more direct one

I have decided to solve it on the Arduino program, because all doors have different MAC Addresses I simply added the MAC address to the end of of the timestamp and because no door will register two ins at the same time that did the trick for me.

这篇关于如何查询同级节点的现有子级并对其进行循环以检测其是否存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆