在 Cloud Firestore 上创建排行榜场景
Creating a leaderboard scenario on Cloud Firestore
我正在玩最近推出的 Cloud Firestore,我想知道是否可以在集合中获取文档的索引来创建排行榜。
例如,假设我想检索用户在排行榜中的位置。我会这样做:
db.collection('leaderboard').doc('usedId')
在那里,我有一个 rank
字段来显示该用户在排行榜中的位置。但是,这意味着我必须创建一个 Cloud Function 来计算用户每次得分变化时的位置。考虑到 Firestore 按 CRUD 操作的数量收费,这可能真的很昂贵。
有更好的方法吗?假设定义一个查询字段(即分数),然后在集合的数组中获取该文档的索引?
您无法找到文档在查询结果中的位置,除非实际 运行 查询并阅读所有文档。这使得按分数排序无法仅确定排名。
您可以通过将等级分组为 10 或 100 个块,然后仅在玩家在它们之间移动时更新等级组来减少更新等级的写入次数。绝对排名可以通过在组内按分数排序来确定。
如果您将这些排名组存储为单个文档,这可能会节省大量资金。
请注意,当您增加文档的作者数量时,这会增加争用,因此您需要根据预期的分数提交率来平衡团队规模,以获得您想要的结果。
aggregation queries 中的技术可以适用于这个问题,但它们本质上具有与您在问题中描述的相同的成本权衡。
您可以在数据库控制台中过滤它。中间栏的右上角,靠近 3 个垂直点。
您还可以使用此 GitHub 存储库来搜索您需要插入到代码中的查询:https://github.com/firebase/snippets-web/blob/f61ee63d407f4a71ef9e677284c292b0a083d723/firestore/test.firestore.js#L928-L928
如果您想根据 'highScores' 对用户进行排名,例如,您可以使用类似于以下内容的前 10 名(并创建一个有序列表或类似列表来表示用户的排名):
db.collection("leaderboard")
.orderBy("highScore", "desc").limit(10) // this is the line you add to filter results
.get()
.then((snapshot) => {
snapshot.docs.forEach((doc) => {
console.log(doc.data());
renderLeaderboard(doc);
});
});
我正在玩最近推出的 Cloud Firestore,我想知道是否可以在集合中获取文档的索引来创建排行榜。
例如,假设我想检索用户在排行榜中的位置。我会这样做:
db.collection('leaderboard').doc('usedId')
在那里,我有一个 rank
字段来显示该用户在排行榜中的位置。但是,这意味着我必须创建一个 Cloud Function 来计算用户每次得分变化时的位置。考虑到 Firestore 按 CRUD 操作的数量收费,这可能真的很昂贵。
有更好的方法吗?假设定义一个查询字段(即分数),然后在集合的数组中获取该文档的索引?
您无法找到文档在查询结果中的位置,除非实际 运行 查询并阅读所有文档。这使得按分数排序无法仅确定排名。
您可以通过将等级分组为 10 或 100 个块,然后仅在玩家在它们之间移动时更新等级组来减少更新等级的写入次数。绝对排名可以通过在组内按分数排序来确定。
如果您将这些排名组存储为单个文档,这可能会节省大量资金。
请注意,当您增加文档的作者数量时,这会增加争用,因此您需要根据预期的分数提交率来平衡团队规模,以获得您想要的结果。
aggregation queries 中的技术可以适用于这个问题,但它们本质上具有与您在问题中描述的相同的成本权衡。
您可以在数据库控制台中过滤它。中间栏的右上角,靠近 3 个垂直点。
您还可以使用此 GitHub 存储库来搜索您需要插入到代码中的查询:https://github.com/firebase/snippets-web/blob/f61ee63d407f4a71ef9e677284c292b0a083d723/firestore/test.firestore.js#L928-L928
如果您想根据 'highScores' 对用户进行排名,例如,您可以使用类似于以下内容的前 10 名(并创建一个有序列表或类似列表来表示用户的排名):
db.collection("leaderboard")
.orderBy("highScore", "desc").limit(10) // this is the line you add to filter results
.get()
.then((snapshot) => {
snapshot.docs.forEach((doc) => {
console.log(doc.data());
renderLeaderboard(doc);
});
});