tl;dr 通过 startAt
, endAt
和 limit
在Firebase中执行基本分页是非常复杂的,必须有一个更简单的方法 .
我正在为大量用户提交构建一个管理界面 . 我的初始(和当前)想法是简单地获取所有内容并在客户端上执行分页 . 然而,在获取2000个记录(每个包含5-6个小数字/字符串字段)时存在明显的延迟,这些记录属于超过1.5mb的数据有效负载 .
目前所有条目都是通过push添加的,但我对于如何通过庞大的列表分页是有点迷茫 .
要获取数据的第一页,我正在使用endAt,其中limit为5:
ref.endAt().limit(10).on('child_added', function(snapshot) {
console.log(snapshot.name(), snapshot.val().name)
})
这导致以下结果:
-IlNo79stfiYZ61fFkx3 #46 John
-IlNo7AmMk0iXp98oKh5 #47 Robert
-IlNo7BeDXbEe7rB6IQ3 #48 Andrew
-IlNo7CX-WzM0caCS0Xp #49 Frank
-IlNo7DNA0SzEe8Sua16 #50 Jimmmy
首先要弄清楚有多少页面我保留了一个单独的计数器,只要有人添加或删除记录就会更新 .
其次,因为我正在使用 push
我无法导航到特定页面,因为我不知道特定页面的最后一条记录的名称,这意味着目前这样的界面是不可能的:
为了简单起见,我决定简单地使用下一个/上一个按钮,这也会带来一个新问题;如果我使用上一个结果集中第一个记录的名称,我可以使用以下内容分页到下一页:
ref.endAt(null, '-IlNo79stfiYZ61fFkx3').limit(5).on('child_added', function(snapshot) {
console.log(snapshot.name(), snapshot.val().name)
})
此操作的结果如下:
-IlNo76KDsN53rB1xb-K #42 William
-IlNo77CtgQvjuonF2nH #43 Christian
-IlNo7857XWfMipCa8bv #44 Jim
-IlNo78z11Bkj-XJjbg_ #45 Richard
-IlNo79stfiYZ61fFkx3 #46 John
现在我有下一页,除了它移动了一个位置意味着我必须调整我的限制并忽略最后一个记录 .
要退回到目前为止我收到的一页,并确定要传递给 startAt
的名称 .
有没有更简单的方法来做到这一点,还是我应该回去取一切?
3 回答
我们正在努力添加“offset()”查询以便于分页 . 我们还将添加一个特殊 endpoints ,以允许您读取某个位置的子节点数,而无需从服务器实际加载它们 .
这两个都需要一点点 . 与此同时,您描述的方法(或在客户端上完成所有操作)可能是您最好的选择 .
如果您的数据结构仅附加,则在编写数据时也可能会进行分页 . 例如:将第一个50放入/ page1,将第二个50放入/ page2等 .
另一种实现此目的的方法是使用两棵树:
ID的树:{id1:id1,id2:id2,id3:id3}
数据树:{id1:...,id2:...,id3:...}
然后,您可以将整个id树(或其中的一大块)加载到客户端,并使用该ID树进行奇特的分页 .
这是每个方向的分页攻击 .
基本上它是
startAtExclusive()
的黑客攻击 . 你可以在id结束时做任何事情 .为了倒退也想出了
endAtExclusive()
.将玩这个更多但似乎与推ids一起使用 . 如果使用firebase查询,请使用
limitToFirst
或limitToLast
替换限制 .