如何查询兄弟节点子节点并遍历检测,实现Firebase跨节点更新?
实现Firebase数据库节点同步与节点检测方案
咱一步步拆解你的需求,从Cloud Function同步逻辑,到Arduino端的写入,再到节点查询遍历,给你讲清楚怎么落地:
一、Cloud Function实现doors到rooms的同步
首先得明确一个前提:你需要在每个doors/{MACaddress}节点下添加一个roomKey字段,用来关联这个门所属的房间roomPushKey——不然函数不知道要把数据写到哪个房间里。
示例Cloud Function代码(JavaScript)
const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(); // 监听doors下任意MAC节点的ins更新 exports.syncDoorInsToRoom = functions.database.ref('/doors/{macAddress}/ins') .onWrite(async (change, context) => { // 获取更新后的ins数据 const newInsData = change.after.val(); if (!newInsData) { // 如果ins被删除,可选择同步删除房间对应数据,按需处理 return null; } // 获取当前门对应的房间key const macAddress = context.params.macAddress; const doorRef = admin.database().ref(`/doors/${macAddress}`); const doorSnapshot = await doorRef.once('value'); const roomPushKey = doorSnapshot.child('roomKey').val(); if (!roomPushKey) { functions.logger.error(`没找到门${macAddress}对应的房间key!`); return null; } // 写入到房间的ins节点 const roomInsRef = admin.database().ref(`/rooms/${roomPushKey}/ins`); // 用update可以保留多个门的数据(以MAC为键),如果要覆盖就用set return roomInsRef.update({ [macAddress]: newInsData }); });
代码说明
- 触发器会监听所有
doors/{MAC}/ins的写入/更新操作; - 先获取当前门对应的房间
roomPushKey,确保数据能写到正确的房间; - 用
update而非set,这样同一个房间下多个门的ins数据会以MAC为键共存,不会互相覆盖。
二、查询遍历兄弟节点,检测目标是否存在
如果需要检测某个节点是否存在,或者遍历某个节点下的所有子节点,用下面的函数就能实现:
1. 检测特定节点是否存在
// 检测rooms/{roomPushKey}/ins/{macAddress}是否存在 const checkTargetNodeExists = async (roomPushKey, macAddress) => { const targetRef = admin.database().ref(`/rooms/${roomPushKey}/ins/${macAddress}`); const snapshot = await targetRef.once('value'); return snapshot.exists(); // 返回true(存在)或false(不存在) };
2. 遍历节点下的所有子节点
比如要遍历某个房间ins下的所有门数据:
const traverseRoomInsNodes = async (roomPushKey) => { const roomInsRef = admin.database().ref(`/rooms/${roomPushKey}/ins`); const snapshot = await roomInsRef.once('value'); // 遍历每个子节点(每个子节点对应一个门的MAC) snapshot.forEach(childSnapshot => { const doorMac = childSnapshot.key; const insData = childSnapshot.val(); functions.logger.info(`门MAC:${doorMac},数据:${JSON.stringify(insData)}`); // 这里可以加自定义逻辑,比如判断数据是否符合要求 }); };
你可以把这两个函数集成到你的Cloud Function里,或者单独调用。
三、Arduino端更新doors节点的代码示例
用Firebase Arduino库实现设备端的写入,这里以ESP32为例:
#include <FirebaseESP32.h> // 替换成你的Firebase项目信息 #define FIREBASE_HOST "你的项目ID.firebaseio.com" #define FIREBASE_AUTH "你的数据库密钥或自定义token" FirebaseData firebaseData; String deviceMac; // 存储设备唯一MAC地址 void setup() { Serial.begin(115200); // 连接WiFi WiFi.begin("你的WiFi名称", "你的WiFi密码"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi连接成功!"); // 获取设备MAC地址,去掉冒号避免路径问题 deviceMac = WiFi.macAddress(); deviceMac.replace(":", ""); Serial.println("设备MAC:" + deviceMac); // 初始化Firebase连接 Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); Firebase.reconnectWiFi(true); } void loop() { // 模拟获取传感器数据(比如门的状态+时间戳) String insData = "{\"status\":\"open\",\"timestamp\":" + String(millis()) + "}"; // 构造写入路径:/doors/{MAC}/ins String writePath = "/doors/" + deviceMac + "/ins"; // 写入数据到Firebase if (Firebase.set(firebaseData, writePath, insData)) { Serial.println("数据更新成功!"); } else { Serial.println("更新失败:" + firebaseData.errorReason()); } delay(5000); // 每隔5秒更新一次,按需调整 }
注意事项
- 数据库规则:测试阶段可暂时开放
doors和rooms的读写权限,生产环境要设置严格的认证规则(比如用Firebase Auth自定义token); - Cloud Function部署:写完代码后,用
firebase deploy --only functions命令部署到Firebase; - 数据格式:如果ins是复杂JSON对象,Arduino里可以用
Firebase.setJSON来写入,更便捷。
内容的提问来源于stack exchange,提问作者Joao Alves Marrucho
相关产品推荐
相关产品推荐

