基于Firebase实现低成本高效排行榜的技术问询
高效获取Firebase实时数据库中用户排名及前后2名数据的方案
我的目标是在数据传输量最低的情况下,高效获取一组有序*且带索引**的子节点列表:
- 有序:按每个用户子节点的
points字段排序 - 索引:仅包含当前用户(特定子节点)前后不超过2名的用户
数据库结构

已实现的前3名查询逻辑
我已经实现了按points排序获取前3名用户的逻辑,代码如下:
val usersRef = FirebaseDatabase.getInstance(DB_LINK).getReference("users").orderByChild("points") usersRef.limitToFirst(3).addValueEventListener( object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { for (ds in snapshot.children) { val points: String = snapshot.child("points").getValue(String::class.java)!! val firstName: String = snapshot.child("firstName").getValue(String::class.java) ?: "" val uid: String = snapshot.key!! // 更新视图 } } override fun onCancelled(error: DatabaseError) {} } )
当前遇到的问题
当当前登录用户不在前3名时,我希望在不查询整个数据库(用户量可达50K)的情况下,获取该用户的总排名、其前2名及后2名用户。全量查询不仅客户端开销大,还会大幅增加Firebase成本。
我查阅了Firebase数据过滤文档及相关方案,但均无法满足需求:要么需要遍历全量数据,要么仍会产生大量读取计费(如用户排名为40000时,需读取39999个节点)。我尝试过用布尔值过滤查询但无果,目前的低效全量查询代码如下:
// 获取所有子节点 usersRef.addValueEventListener( object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { for (ds in snapshot.children) { val points: String = snapshot.child("points").getValue(String::class.java)!! val firstName: String = snapshot.child("firstName").getValue(String::class.java) ?: "" val uid: String = snapshot.key!! // 仅当用户排名与当前用户排名差在±2范围内时更新视图 } } override fun onCancelled(error: DatabaseError) {} } )
期望效果
我希望实现如下排行榜效果(样式已完成,逻辑待实现):
请问是否有可行方案?或有其他替代方案?
补充:我发现Firestore提供的聚合查询(aggregation queries)可能有助于降低成本,正在进一步研究。
内容的提问来源于stack exchange,提问作者Aly Mobarak
相关产品推荐
相关产品推荐

