我在 Firestore 中有 10k 个用户,每个用户的 documentId 是他们的 uid,分数注册到他们的文档中。为了找到Leaderboard的Top 20,它成功地根据其分数查询了Top 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
to 39
, etc.
还可以设置查询offset
返回将在设定位置返回的结果,但是这是非常不推荐的,因为使用offset
,您会为跳过的每个文档进行写入。因此,如果您想获取倒数 20 名玩家,您最终将等待 9,980 个文档读取!
您可以查看使用查询游标对数据进行分页 https://firebase.google.com/docs/firestore/query-data/query-cursors了解更多信息。
就您现有的数据结构而言......
要通过用户标识符找出用户的排名,您可能需要手动缓存其当前排名。您可以设置一个计划任务来计算玩家的排名,每天计算每个玩家的排名。这将是昂贵的,因为每次执行的写入次数会随着用户数量的变化而变化;并且由于它是基于缓存的,因此受到时间限制(玩家在下次计算之前不会看到他们的排名变化。)
更简单的方法是取最高分、最低分,然后根据用户数量将它们的分数缩放到等效排名(这不一定必须是线性比例,您可以使用钟形曲线示例),但是这并不精确,并且多个用户可能看起来具有相同的排名。但是,根据您的用例,这可能是一个合适的让步。
另一种方法是让用户在尝试查看自己的排名时自行更新排名系统。它可以查看在其之前和之下的用户的分数,并通过确定它是否应该位于相邻记录之前或之后来有效地保持排名。这将需要更复杂的规则结构来防止作弊,并且会在排名数据集中引入不连续性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)