Javascript 使用Firebase侦听嵌套更改的正确方法是什么?

Javascript 使用Firebase侦听嵌套更改的正确方法是什么?,javascript,firebase,Javascript,Firebase,背景: 我正在尝试使用Firebase、Twilio和Node.js通过浏览器发送短信。我在Firebase中的当前数据结构如下所示: { messages : { +15553485 : { FB-GENERATED-KEY-1 : { body: "hello world" timestamp: 1461758765472 } }, { FB-GENERATED-KEY-3 : { body: "I love dogs"

背景:

我正在尝试使用Firebase、Twilio和Node.js通过浏览器发送短信。我在Firebase中的当前数据结构如下所示:

{ messages :
  { +15553485 :
    { FB-GENERATED-KEY-1 :
      { body: "hello world"
        timestamp: 1461758765472 }
    },
    { FB-GENERATED-KEY-3 :
      { body: "I love dogs"
        timestamp: 1461758765475 }
      }
    }
  },
  { +15550000 :
    { FB-GENERATED-KEY-2 :
      { body: "goodbye world"
        timestamp: 1461758765473 }
    },
    { FB-GENERATED-KEY-4 :
      { body: "I love cats"
        timestamp: 1461758765476 }
      }
    }
  }
}
ref.child('messages').on('child_added', function (snapshot) {
    var phone = snapshot.key();
    ref.child('messages').child(phone).on('child_added', function (message) {
        //send SMS
    }, function (error) {

    });
}, function (error) {

});
当通过前端向Firebase添加消息时,后端需要得到通知,以便通过Twilio发送SMS。当后端从手机(通过Twilio)获得回复时,它会将其添加到Firebase

问题:

当我监听某个线程的更改时,我会收到该电话号码发送/接收的所有消息。显然后端不想再次发送所有消息,所以我只对添加到线程中的最新消息感兴趣

此外,我似乎无法轻易地得到下面有信息的电话号码(钥匙)

我所尝试的:

ref.child('messages')。on('child_added',…)
-这适用于在
/messages
中添加的新电话号码,但是Firebase不发送新电话号码(key),只发送从
FB-GENERATED-key-2
开始的所有内容

ref.child('messages')。on('child_changed',…)
-这将返回线程中的所有消息,而不仅仅是新消息。我可以在服务器上排序并找到最新的消息,但这似乎会很快变得很重——如果你已经发送了数千条消息怎么办

在根级别存储消息(也就是将树展平)并将号码存储为属性可能会起作用,但我需要使用电话号码作为一种索引,以便稍后连接其他数据(如外键)

问题:

  • 如何仅在收听家长
    /messages
    上的活动时获取最新消息,而不是特定的电话号码
  • 使用
    子事件时如何获取密钥(电话号码)
  • 这种数据结构有意义吗

您可以通过调用您添加的
子侦听器返回的快照来获取Firebase密钥

然后可以添加另一个嵌套侦听器,如下所示:

{ messages :
  { +15553485 :
    { FB-GENERATED-KEY-1 :
      { body: "hello world"
        timestamp: 1461758765472 }
    },
    { FB-GENERATED-KEY-3 :
      { body: "I love dogs"
        timestamp: 1461758765475 }
      }
    }
  },
  { +15550000 :
    { FB-GENERATED-KEY-2 :
      { body: "goodbye world"
        timestamp: 1461758765473 }
    },
    { FB-GENERATED-KEY-4 :
      { body: "I love cats"
        timestamp: 1461758765476 }
      }
    }
  }
}
ref.child('messages').on('child_added', function (snapshot) {
    var phone = snapshot.key();
    ref.child('messages').child(phone).on('child_added', function (message) {
        //send SMS
    }, function (error) {

    });
}, function (error) {

});

Firebase API允许您侦听值的更改或对子级的操作。它没有办法倾听孙辈的变化

在NoSQL数据库中,通常需要根据应用程序使用数据的方式对数据进行建模。如果我看一下您的特定用例:

当通过前端向Firebase添加消息时,后端需要得到通知,以便通过Twilio发送SMS

我在这里看到一个队列:

smsQueue: {
  pushId1: {
    number: "+15553485",
    body: "hello world",
    timestamp: 1461758765472 
  },
  pushId2: {
    number: "+15550000",
    body: "goodbye world",
    timestamp: 1461758765473
  },
  pushId3: {
    number: "+15553485",
    body: "I love dogs",
    timestamp: 1461758765475
  },
  pushId4: {
    number: "+15550000",
    body: "I love cats",
    timestamp: 1461758765476 
  }
}

使用这种结构,您的后端(希望使用)可以从队列中获取每个任务,调用twilio并从队列中删除项目。

Ah!当然,
snapshot.val()
为您提供值,
snapshot.key()
为您提供键是有道理的!当一条新消息添加了一个新号码时,您的答案应该适用,但是当一条新消息添加了一个现有号码时,您的答案会如何呢?我是否对嵌套侦听器执行类似的操作,但改为使用
child\u changed
事件?@BenjaminHumphrey您的意思是在实现此功能时,您已经有了一个现有的数据集?在这种情况下,我可能会在外部侦听器中使用
one('value')
执行类似的操作。对于新的号码,内部侦听器将侦听所有未来的新消息。不,我的意思是当新消息发送到数据库中已经存在的号码时。
child\u added
事件不会在顶层触发,因为没有添加新号码,只有一条新消息作为孙子添加。不过,我已经阅读了更多有关Firebase中结构化数据的内容,听起来我应该进一步将所有内容展平,以便/消息和/数字都位于根级别。请参阅。@BenjaminHumphrey如果为一个新号码添加的外部
child\u触发一次,则为该号码添加的内部
child\u将为每个新消息触发一次。当然,扁平化的数据结构会使这种情况变得更容易;)谢谢你的回答
firebase队列
看起来很有趣,我来看看。但是,我确实希望将消息持久化到数据库中,因此这与您概述的队列用例不同。