如何在Firebase中按升序或降序检索分页子项?

cay*_*ood 9 javascript pagination firebase

假设我正在使用firebase作为评论系统,我想检索给定主题的评论,但是在一个主题中有很多评论我不想一次全部检索它们.我还希望最新的评论显示在最上面.

似乎以相反的顺序显示firebase记录的唯一方法是将它们全部检索,然后反过来迭代它们.

这可能会对大型数据集变得非常笨重,特别是对于移动客户端.

有没有更好的方法?从Firebase查询分页数据的升级或降序的一般和首选解决方案是什么?

Pan*_*olo 13

更新的答案

@Tyler回答stackoverflow.com/a/38024909/681290对这个问题是一个更新,更方便的答案

TL; DR

如果您要做的是:

ref.orderBy(field, 'DESC').offset(n).limit(x)
Run Code Online (Sandbox Code Playgroud)

此外,在Firebase github中,有一些不受支持的工具可以进行分页,尽管只是按升序排列.

否则,这是我自己发现的最接近的解决方案,或者到目前为止在网上.我故意将这个问题解释为通用的,而不仅仅是关于OP所要求的时间字段.


使用优先级

目标是使用setWithPriority()setPriority()儿童能够以后获得有序数据orderByPriority().

问题:

  • 我没有看到使用索引priority字段的优势?(实际上,优先级存储为一个被调用的底层字段.priority,在导出json数据时可以看到)
  • 许多用例难以维护,以确定要设置的优先级值

带有负数据的冗余子字段

例如,timeRev除了time能够首先获得最新项目之外,我们还可以使用负时间戳索引字段.

ref.orderByChild('timeRev')
   .limitToFirst(100);
Run Code Online (Sandbox Code Playgroud)

问题:

  • 它增加了应用程序的复杂性:需要维护其他字段
  • 可以打破字段的原子性(例如,score字段可以立即更新,不确定是否可以使用两个字段,一个是正字段,一个是负字段)
  • 我觉得当只有有这种解决方法被用来limit()在火力地堡API,但有点过时了,现在我们就可以使用limitToFist(),limitToLast()以及范围查询(见下文)

使用limitToLast()和endAt()范围查询

这让我们避免负面和冗余领域:

ref.orderBy('time')
   .limitToLast(100)
Run Code Online (Sandbox Code Playgroud)

这对于时间戳字段应该非常有效,因为通常这是一个唯一的字段.

在使用之前,只需要反转生成的项目数组.(只记得Array.prototype.reverse()是可变的,所以它会改变你的数组)

问题:

  • API文档说只有有序键值可以设置为边界startAtendAt边界.如果许多项共享相同的值,则无法将数据集拆分为固定长度的偏移量.

保存score值的以下项的示例:

{
  items: {
    a: {score: 0},
    b: {score: 0},
    c: {score: 1},
    d: {score: 1},
    e: {score: 2},
    f: {score: 5}
  }
}
Run Code Online (Sandbox Code Playgroud)

第一页查询以获得最佳得分项:

ref.child('items').orderByChild('score')
   .limitToLast(3)
Run Code Online (Sandbox Code Playgroud)

结果:

{
  d: {score: 1},
  e: {score: 2},
  f: {score: 5}
}
Run Code Online (Sandbox Code Playgroud)

请注意,子集的第一项具有1分数,因此我们尝试通过选择分数为1或更低的所有项目来获取上一页:

ref.child('items').orderByChild('score')
   .endAt(1)
   .limitToLast(3)
Run Code Online (Sandbox Code Playgroud)

根据该查询,我们得到b,c,d项目,而不是a,b,c项目,这是根据API文档预期的,因为它endAt(1)是包容性的,因此它将尝试获得所有分数1,并且无法对之前已经返回的分数进行排序.

解决方法

这可以通过不期望每个子集保持相同数量的记录并且丢弃已经加载的那些来减轻.

但是,如果我的应用程序的第一百万用户有0分数,则该子集不能分页,因为endAt偏移是无用的,因为它基于而不是记录数.

我没有看到此用例的任何解决方法,我猜Firebase不适用于此:-)

编辑:最后,我使用Algolia用于所有与搜索相关的目的.它是一个非常好的API,我希望谷歌最终收购Algolia以整合Firebase和Algolia,因为它们的互补性接近100%!免责声明:没有股份!:-)