假设我正在使用firebase作为评论系统,我想检索给定主题的评论,但是在一个主题中有很多评论我不想一次全部检索它们。我还希望最新的评论显示在最上面。
似乎以相反的顺序显示firebase记录的唯一方法是将它们全部检索,然后反过来迭代它们。
对于大型数据集,这可能非常笨拙,特别是对于移动客户端。
还有更好的方法吗?从Firebase查询分页数据的通用和首选解决方案是升序还是降序?
答案 0 :(得分:11)
更新回答
@Tyler answer stackoverflow.com/a/38024909/681290是这个问题的最新且更方便的答案
<强> TL; DR 强>
如果您要做的是:
,则无法解决ref.orderBy(field, 'DESC').offset(n).limit(x)
此外,在Firebase github中,有不受支持的工具that do pagination,但仅限升序。
否则,以下是我自己找到的最接近的解决方案,或者到目前为止在网上找到的解决方案。我故意将这个问题解释为通用的,而不仅仅是关于OP所要求的时间字段。
使用优先级
目标是让儿童使用setWithPriority()
和setPriority()
,以便稍后使用orderByPriority()
获取有序数据。
问题:
priority
字段的优势? (实际上,优先级存储为名为.priority
的基础字段,导出json数据时可以看到)包含负数据的冗余子字段
例如,除了timeRev
之外,我们还可以使用负时间戳time
索引字段来首先获取最新项目。
ref.orderByChild('timeRev')
.limitToFirst(100);
问题:
score
字段可以立即更新,不确定它是否可以使用两个字段,一个是正字段,一个是负字段“limit()
时会使用此解决方法,但由于我们可以使用limitToFist()
,limitToLast()
和范围查询(请参阅下文),因此有点过时了) 使用limitToLast()和endAt()
范围查询
这让我们避免消极和冗余的领域:
ref.orderBy('time')
.limitToLast(100)
这对于时间戳字段应该非常有效,因为通常这是一个唯一的字段。
在使用之前,只需要反转生成的项目数组。 (只记得Array.prototype.reverse()
是可变的,所以它会改变你的数组)
问题:
startAt
或endAt
边界。如果许多项共享相同的值,则无法将数据集拆分为固定长度的偏移量。以下项目持有score
值的示例:
{
items: {
a: {score: 0},
b: {score: 0},
c: {score: 1},
d: {score: 1},
e: {score: 2},
f: {score: 5}
}
}
首页查询以获得最佳得分项目:
ref.child('items').orderByChild('score')
.limitToLast(3)
结果:
{
d: {score: 1},
e: {score: 2},
f: {score: 5}
}
请注意,该子集的第一项具有1
分数,因此我们尝试通过选择分数为1
或更低的所有项目来获取上一页:
ref.child('items').orderByChild('score')
.endAt(1)
.limitToLast(3)
根据该查询,我们会获得b,c,d
个项目,而不是a,b,c
个项目,这些项目是根据API文档预期的,因为endAt(1)
具有包容性,因此它会尝试获取所有分数为1,并且无法对之前已经返回的内容进行排序。
解决方法强>
可以通过不期望每个子集保持相同数量的记录并丢弃已经加载的记录来减轻这种情况。
但是,如果我的应用的第一百万用户的分数为0
,则此子集无法进行分页,因为endAt
偏移无用,因为它基于在值而不是记录数。
我没有看到此用例的任何解决方法,我认为Firebase不适用于此: - )
编辑:最后,我使用Algolia用于所有与搜索相关的目的。它是一个非常好的API,我希望谷歌最终收购Algolia以整合Firebase和amp; Algolia,因为它们的互补性接近100%!免责声明:没有股份! : - )
答案 1 :(得分:0)
这是firebase文档的解决方案:
查询查询= city.orderBy(“ name”,Direction.DESCENDING).limit(3);
https://firebase.google.com/docs/firestore/query-data/order-limit-data