Javascript Firebase获取特定密钥的所有值

Javascript Firebase获取特定密钥的所有值,javascript,firebase,firebase-realtime-database,Javascript,Firebase,Firebase Realtime Database,我在Firebase上有一个用户表,每个用户都有一封电子邮件道具 结构如下所示: Users->useruid(看起来像n8habbjgabob2ranfuabu3aaaga2af)->userobj,其中包括email道具 我想获得所有用户的电子邮件(约100万封)的数组 我怎样才能最有效地做到这一点 附言: 我试过: usersRef.startAt(0).endAt(20).once("value", function(snapshot) { console.log('FIRST 20

我在Firebase上有一个
用户
表,每个用户都有一封
电子邮件
道具

结构如下所示:

Users
->
useruid
(看起来像
n8habbjgabob2ranfuabu3aaaga2af
)->
userobj
,其中包括
email
道具

我想获得所有用户的电子邮件(约100万封)的数组

我怎样才能最有效地做到这一点

附言:

我试过:

usersRef.startAt(0).endAt(20).once("value", function(snapshot) {
  console.log('FIRST 20');
  console.log(snapshot.val()); // null
});

但这是失败的。

在数据读取方面,最有效的方法可能是对数据进行非规范化。您可以将电子邮件地址存储在单个用户节点和
emailAddresses
节点中。然后,您可以直接查询
电子邮件地址
节点以获取电子邮件列表

不过,一次大约1百万个电子邮件地址节点可能太多了。我可能会把它切成块。。。我猜

更新 “分块抓取”本质上是分页。在尝试推出自己的分页解决方案之前,我会尝试使用现成的东西

要签出的分页库:

  • :这是Firebase开发的,但他们说这是实验性的,还没有准备好用于生产。但是,它可能仍然值得玩弄
  • :这是一个社区成员开发的,看起来相当可靠
如果您想进行自己的分页,请查看:

  • @加藤在《他》一书中的回答就实时数据集分页的潜在问题提出了一个有趣的观点,但随后提供了一些很好的起始代码
  • 这是关于我认为是我上面链接的firebase paginator库的一部分的代码

    • 每个人在回答中都说这是一件容易的事情,但没有有效的解决方案。以下是我的想法:

      usersRef.orderByChild('uid').limitToFirst(100).once('value', function (snapshot) {
        var users = snapshot.val()
        var uids = Object.keys(users);
        var lastUid = uids[uids.length - 1];
      
        // could be another property than uid, for example email, or username. Ps.: Consider that the last ID from the previous chunk will be duplicated.
        usersRef.orderByChild('uid').startAt(lastUid).limitToFirst(100).once('value', function (snapshot) {
          var users = snapshot.val()
          var uids = Object.keys(users);
          console.log(uids);
          var lastUid = uids[uids.length - 1];
          // re-run function until done
        })
      })
      

      由于这是一次性交易,一个选项是简单地迭代父“数据”节点中的每个节点以捕获子数据,剥离电子邮件地址并将其转储到文件中

      你想要的活动是

      添加的子项:检索项目列表或侦听列表中的添加项 物品的数量。对于每个现有子级和子级,此事件将触发一次 然后,每次将新的子级添加到指定的路径时。这个 将向侦听器传递一个包含新子级数据的快照

      迭代数据节点中所有子节点的代码如下

      var dataRef = firebase.database().ref('myRootRef/data');
      datRef.on('child_added', function(data) {
        //data.val() will contain the child data, such as the email address
        //append it to a text file here (for example), save to disk etc.
      });
      
      这里的关键是,该事件对每个子级触发一次,类似于对数组中的所有索引进行迭代

      这将检索每个子节点并将其呈现给您的应用程序,一次一个,迭代节点中的所有子节点


      有这么多节点需要花一段时间来仔细研究。

      使用childAdded事件迭代所有用户节点非常简单(因此一次只加载一个节点)。但更大的问题是你为什么要这么做?可能有比一次加载它们更好的方法,但我们需要了解您的使用情况。我正在我的网站上发布一份时事通讯,我需要收集所有当前的电子邮件。这是一次性的开始,因为新注册的电子邮件将在用户注册时添加。如果查询正常,我会将所有数据保存在Firebase中,每次发送时事通讯时,我都会查询+成批发送。似乎没有人真正知道如何完成这项工作。Firebase需要做大量工作,才能成为大型站点的可行数据库解决方案(100万用户并不是很大)。不管怎样,我想出了一个解决办法,一个奇怪但有效的办法。事实上,我的评论是一个非常简单和直截了当的答案。使用添加的childAdded对所有数据进行迭代。这需要一段时间,但需要大约10行代码。如何将其分块获取?如果分页使用
      orderByChild
      ,我认为您的第一个查询也应该是:
      usersRef.orderByChild('uid')。limitToFirst(100)
      。(目前,这并不重要,因为键和子项的顺序是相同的,但如果您使用类似子项的
      电子邮件
      ——根据您的评论——第一次查询和后续查询之间的顺序将不同。)