9

例如,我有以下数据库结构:

/ 
+ users
  + 1
    + items
      + -xxx: "hello"
  + 2
    + items

然后;

var usersRef = new Firebase("https://mydb.firebaseio.com/users");
usersRef.on("child_changed", function(snapshot) {
  utils.debug(JSON.stringify(snapshot.exportVal()));
});

如果将值“world”推送到“/users/1/items”,我可能会得到:

{"items": {"-xxx": "hello", "-yyy": "world"}}

那么,如何判断哪一个被改变了呢?

我需要对“/users/$id/items”的每个引用都打开(“child_added”)?

注意:我正在尝试在 node.js 中编写一个管理进程。

4

2 回答 2

23

child_changed 事件仅提供有关哪个直接子级已更改的信息。如果数据结构中更深的节点发生更改,您将知道哪个直接子节点受到影响,但不知道更改数据的完整路径。这是设计使然。

如果您想要精确更新更改的内容,您应该递归地将回调附加到您关心的所有元素。这样,当一个项目发生变化时,你就会知道该项目是由哪个回调触发的。Firebase 实际上针对这个用例进行了优化;附加大量的回调——甚至数千个——应该可以正常工作。在幕后,Firebase 将所有回调聚合在一起,并且只同步所需的最少数据集。

因此,对于您的示例,如果您想在每次为任何用户添加新项目时收到警报,您可以执行以下操作:

var usersRef = new Firebase("https://mydb.firebaseio.com/users");
usersRef.on("child_added", function(userSnapshot) {
  userSnapshot.ref().child("items").on("child_added", function(itemSnapshot) 
    utils.debug(itemSnapshot.val());
  });
});

如果您正在处理大量用户(数十万或数百万),并且同步所有数据是不切实际的,那么还有另一种方法。与其让您的服务器直接监听所有数据,不如让它监听一系列更改。然后,当客户端将项目添加到他们的项目列表中时,他们也可以将项目添加到此队列中,以便服务器知道它。

这是客户端代码的样子:

var itemRef = new Firebase("https://mydb.firebaseio.com/users/MYID/items");
var serverEventQueue = new Firebase("https://mydb.firebaseio.com/serverEvents");
itemRef.push(newItem);
serverEventQueue.push(newItem);

然后,您可以让服务器在该队列上侦听 child_add 并在事件进入时处理它们。

于 2013-03-01T18:31:05.607 回答
5

Andrew Lee 给出了一个很好的答案,但我认为你应该尝试使用云功能。像这样的东西应该工作:

exports.getPath = functions.database.ref('/users/{id}/items/{itemId}')
.onWrite(event => {
  // Grab the current value of what was written to the Realtime Database.
  const original = event.data.val();
  console.log('user id', event.params.id);
  console.log('item id', event.params.itemId);
});
于 2017-05-13T12:37:35.507 回答