【发布时间】:2018-10-18 11:04:39
【问题描述】:
我正在尝试在 firebase 数据库中更新(添加)新的子节点。在这种情况下,我正在更新两个节点 and_"door/{MACaddress_1}/ins"_ & _"doors/{MACaddress_2}/ins"_ 并且这两个节点都需要通过 Google Cloud 函数写入名为 “房间/{roomPushKey}/ins”。
我将通过物联网设备上的 Arduino 程序更新初始 “门” 节点,该设备具有连接到数据库的唯一 MAC 地址到 '/doors/' + {MAC 地址} + '/ins'。
这些是基本条件:
1) 如果 "rooms/{roomPushKey}/ins" 尚未创建,则创建它(防止写入第一个数据时出现未定义或空错误情况)。
2) 两个“门” 通常都有不同的子键。所以我不能简单地覆盖兄弟 "room" 节点的数据,因为这会删除未更新的一扇门的节点。这里我需要确保 "rooms/{roomPushKey}/ins" 只从每个 门 获取新数据。 p>
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,
}
}
}
我需要克隆 last "key:pair" 添加到 "doors/{MACaddress}/ins" if em>last "key:pair" 已经在 _"rooms/{roomPushKey}/ins"_ 节点中,忽略所有 "doors/{ 中已经存在的 "key:pairs" MACaddress}/ins" 个节点。
类似这样的:
有什么想法吗?
【问题讨论】:
-
对象没有顺序,所以 "last" 不能保证它是最后添加的。应该为此使用时间戳
-
谢谢@charlietfl。是的,我正在编写时间戳,但有 0.01% 的机会同时编写两个时间戳。发生这种情况时,函数将具有不同的执行时间(这将允许我在最后一个检查数据库的函数中添加后缀)。这就是我开发这个功能的原因。
-
我正在物联网设备上运行一个 Arduino 程序,该设备具有一个唯一的 MAC 地址,该地址将数据库连接到“/doors/”+{MAC 地址}+“/ins”。有一个传感器可以做到这一点。
-
@JoaoAlvesMarrucho 您能否强调一下我们上周制定的解决方案中什么不起作用(或应该以不同的方式起作用)?
-
@JoaoAlvesMarrucho 我看到你想出了几个解决方案,一个是 Renaud Tarnec 提出的,另一个是你发现的(更有效)。请您将它们都发布为答案吗?只是为了保持论坛有序和有用。
标签: javascript firebase firebase-realtime-database google-cloud-functions