【问题标题】:Firebase get all values of specific keyFirebase 获取特定键的所有值
【发布时间】:2016-12-15 21:22:04
【问题描述】:

我在 Firebase 上有一个 users 表,每个用户都有一个 email 属性。

结构如下:

Users -> User UID(看起来像 n8haBbjgablobA2ranfuabu3aaaga2af) -> User Obj 其中包括 email 道具。

我想获取所有用户电子邮件的数组 (~1m)。

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

附言:

我试过了:

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

但这失败了。

【问题讨论】:

  • 使用 childAdded 事件迭代所有用户节点非常简单(因此一次只加载一个)。但更大的问题是你为什么要这样做?可能有比一次加载它们更好的方法,但我们需要了解您的用例。
  • 我开始在我的网站上发布时事通讯,我需要收集所有当前的电子邮件。这是一次性开始的事情,因为新注册的电子邮件将在用户注册时添加。
  • 如果查询正常,我会将所有数据保存在 Firebase 中,每次发送时事通讯时,我都会查询 + 分块发送。
  • 似乎没有人真正知道如何完成这项工作。 Firebase 需要做很多工作才能成为大型网站的可行数据库解决方案(而且 100 万用户并不是很大)。无论如何,我想出了一个解决方案,一个奇怪但有效的解决方案。
  • 实际上,我的评论是一个超级简单直接的答案。使用 childAdded 遍历所有数据。这需要一段时间,但需要大约 10 行代码。

标签: javascript firebase firebase-realtime-database


【解决方案1】:

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

仍然有大约 100 万个电子邮件地址节点可能一下子就太多了。我可能会大块地抓住它……我猜。

更新

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

要签出的分页库:

  • Firebase Utils Pagination:这是由 Firebase 开发的,但他们说它是实验性的,还没有准备好用于生产。但是,它可能仍然值得一玩。
  • firebase-paginator:这是由社区成员开发的,看起来很可靠。

如果您想滚动自己的分页,请查看:

  • @kato 在this StackOverflow answer 中的回复他对实时数据集分页的潜在问题提出了一个有趣的观点,但随后提供了一些很好的入门代码
  • Here's a good blog entry 谈到了我认为是我在上面链接的 firebase-paginator 库的一部分的代码

【讨论】:

  • 如何分块抓取?
【解决方案2】:

每个人的回答都说这是一件容易的事,但没有可行的解决方案。这是我想出的:

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
  })
})

【讨论】:

  • 如果您的分页使用orderByChild,我认为您的第一个查询也应该:usersRef.orderByChild('uid').limitToFirst(100)。 (目前,键和子顺序相同并不重要,但如果您使用像email 这样的子代 - 根据您的评论 - 第一个查询和后续查询之间的顺序会有所不同。)
【解决方案3】:

由于这是一次性交易,因此一种选择是简单地遍历父“数据”节点中的每个节点,捕获子数据,剥离电子邮件地址并将其转储到文件中。

你想要的事件是

child_added:检索项目列表或监听列表的添加 的项目。此事件为每个现有的孩子触发一次,并且 然后每次将新的孩子添加到指定的路径时。这 监听器被传递一个包含新孩子数据的快照。

并且迭代数据节点中所有子节点的代码是

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.
});

这里的关键是每个孩子都会触发一次此事件,类似于遍历数组中的所有索引。

这将检索每个子节点并将其呈现给您的应用,一次一个子节点,遍历节点内的所有子节点。

要处理这么多节点需要一段时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多