Firebase 实时数据库:如何在按值排序后围绕特定键检索 10 条记录?

Posted

技术标签:

【中文标题】Firebase 实时数据库:如何在按值排序后围绕特定键检索 10 条记录?【英文标题】:Firebase realtime database: how can I retrieve 10 records around a specific key after ordered by value? 【发布时间】:2017-10-21 02:36:51 【问题描述】:

我使用 Unity 在 Firebase 实时数据库中创建了一个简单的排行榜:

键对应用户名,值对应用户分数。

我想要

    检索前 20 条记录 按分数排序时,检索给定用户名周围的 5 条记录(上 2 条、自身和下 2 条)。

我设法通过以下查询检索前 100 名:

FirebaseDatabase.DefaultInstance.GetReference (LEADERBOARD_TABLE_CAPTION).Child (leaderboardName).OrderByValue ().LimitToLast (20)

我使用 LimitToLast 是因为排序是按升序完成的。

结果如下:

1.test31,987
2.test85,975
3.test67,943
4.test94,941
5.test95,940
6.test71,929
7.test16,917
8.test64,911
9.test100,906
10.test42,870
11.test54,863
12.test88,861
13.test5,859
14.test97,844
15.test46,836
16.test26,765
17.test52,764
18.test4,763
19.test70,756
20.test51,742

然后对于第二个任务,我想检索用户名周围的分数,比如说“test100”。我想检索这样一个结果(注意test100不需要在前20):

 7.test16,917
 8.test64,911
 9.test100,906
 10.test42,870
 11.test54,863

我想运行这样的查询,从 test100 开始并限制到前 3 个,然后在 test100 限制到最后 3 个结束,但以 按值排序 方式。没有这样的功能(我无法找到)。 StartAt 和 EndAt 始终基于 value ,但我无法根据分数 906 将查询居中(可能有很多用户的分数为 906)。

即使只有一个 906,我的解决方案仍然不起作用。当我居中并获得大约 906 的前 2 和后 2 分数时,我不知道居中值的排名,也无法显示我当前用户的当前排名。最低效的解决方案是检索所有按值排序的分数并搜索当前用户,但当我有 10.000 条记录时,这不是解决方案。

我该怎么做?

最好的问候,

费西斯

【问题讨论】:

【参考方案1】:

Firebase 数据库查询可以检索开始于特定键/值的项目或结束于特定键/值的项目。要检索特定键之前的 5 项和特定键之后的 5 项,您需要使用两个查询。

leaderboard = FirebaseDatabase.DefaultInstance.GetReference(LEADERBOARD_TABLE_CAPTION).Child(leaderboardName);
var anchorItemKey = "...";
Query itemsBefore = leaderboard.orderByKey().endAt(anchorItemKey).limitToLast(6);
Query itemsAfter = leaderboard.orderByKey().startAt(anchorItemKey).limitToFirst(6);

上面的每个查询将检索(最多)6 个项目,这比您需要的多一个。这样做的原因是查询也将检索锚项本身。

更新:如果您想根据分数检索项目,围绕特定键,您可以使用带有两个参数的 startAt() 方法:

leaderboard = FirebaseDatabase.DefaultInstance.GetReference(LEADERBOARD_TABLE_CAPTION).Child(leaderboardName);
var anchorItemKey = "...";
var scoreOfAnchorItem = ...;
Query itemsBefore = leaderboard.orderByChild("score").endAt(scoreOfAnchorItem, anchorItemKey).limitToLast(6);
Query itemsAfter = leaderboard.orderByChild("score").startAt(scoreOfAnchorItem, anchorItemKey).limitToFirst(6);

使用此变体,Firebase 将按分数对项目进行排序,然后返回锚项目键周围的项目。

【讨论】:

这个 orderByKey() 查询不是按字母顺序排列用户名吗?我想根据分数对用户名进行排序,而不是锚定到特定的用户名...不过我会尽快尝试 嗯,好的。从代码 sn-p 中不清楚您是按分数排序的。我更新了我的答案以包含一个示例。 非常感谢弗兰克,我尝试了您的解决方案(花了一点时间),但我遇到了最后一个问题。我可以显示锚分数前后的 3 个项目,但是,我无法获得锚分数在整个列表中的排名。我必须向用户显示“这里是前 100 名”、“你是第 305 名”和“这是第 303 名第 304 名第 305 名(你)第 306 名第 307 名的分数”。

以上是关于Firebase 实时数据库:如何在按值排序后围绕特定键检索 10 条记录?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 4 Firebase angularfire 按值对列表进行排序

Firebase&Filtering按值/键排序

为啥在按值返回时总是调用复制构造函数

Android:Firebase 花费太多时间来获取数据

在按值与引用构造数据读取器时配置数据读取器

Firebase 按降序对数据进行排序。 (只排序了一半。)