firebase - 在 Firestore 中获得玩家的排名
问题描述
我在 Firestore 中有 10k 个用户,每个用户的 documentId 是他们的 uid,并且分数已注册到他们的文档中。查找排行榜前 20 名,根据其分数成功查询前 20 名用户,如使用复合索引。
let query = usersRef.order(by: scores, descending: true).limit(to: 20)
query.getDocuments() //to get 20 documents
不幸的是,我找不到一种方法来处理当前未进入前 20 名的玩家的排名(索引号)。为什么 Firestore 不根据每个用户的 uid 返回查询的排名(索引号)?或任何其他方式来解决 Firestore 中的问题?
解决方案
您可以使用startAfter
/startAt
并提供文档参考来抵消您的查询。
因此,如果您有前 20 条记录的列表,您可以重复完全相同的查询,但将其指定为startAfter
列表中的最后一个元素,然后您将返回位置记录20
,39
等等。
您还可以将查询设置offset
为返回将在设置位置返回的结果,但是这是非常不推荐的,因为使用offset
,您会为您跳过的每个文档进行写入。因此,如果您想获取最后 20 名玩家,您最终将等待 9,980 次文档读取!
您可以查看使用查询游标对数据进行分页以获取更多信息。
就您现有的数据结构而言...
要通过用户标识符找出用户的排名,您可能需要手动缓存他们当前的排名。你可以设置一个定时任务来计算玩家的排名,每天计算每个玩家的排名。这将是昂贵的,因为每次执行的写入次数会随着您的用户数量而增加;并且由于它是基于缓存的,受时间限制(玩家在下次计算之前不会看到他们的排名变化。)
一种更简单的方法是取最高分、最低分,并根据用户数量将他们的分数缩放到同等排名(这不一定是线性比例,您可以使用钟形曲线例如),但是这将是不精确的,并且多个用户可能看起来具有相同的排名。但是,根据您的用例,这可能是一个合适的让步。
另一种方法是让用户在尝试查看自己的排名时自己更新排名系统。它可以查看在它之前和在它下面的用户的点,并通过确定它应该在相邻记录之前还是之后来有效地保持等级。这将需要更精细的规则结构来防止作弊,并且会在您的排名数据集中引入不连续性。
推荐阅读
- wso2 - WSO2 身份服务器端口配置
- kubernetes - 为什么重新安排时 OOMKilled 吊舱没有准备好?
- swift - Swif 结构不符合 Codable
- java - 可执行 jar 不读取 .properties 文件(Build.xml)
- c# - 如何使用 C# 在 CRM 中的新实体中设置查找字段的值
- node.js - 节点:res.locals 未定义?
- android - Android kotlin androidx.viewpager.widget.ViewPager::currentTab 上的两种方式数据绑定
- makefile - 为什么 ifeq 放在不同的地方会产生不同的效果?
- java - 创建 JSONObject 实例时出现问题
- jquery - 使用变量传递类名