考虑Firebase数据库的以下结构:
我想运行一个返回所有游戏节点的查询,其中每个游戏节点(玩家)的孩子将根据得分进行排序。游戏节点包含每个玩家的UID,并且每个UID节点包含玩家的得分。我也存储其他数据,但是,为了这个例子,我将只使用得分。
我可以使用一个查询执行此操作吗?就像是
rootRef.child("root").orderByChild("score")
?不幸的是,这似乎不起作用。
或者实现这一目标的唯一方法是手动排序客户端上的项目?
@Puf - 希望你能回答:)
答案 0 :(得分:1)
如果您希望按玩家得分排序的所有游戏,您需要做的就是使用.indexOn
规则。
{
"rules": {
"$gameId": {
".indexOn": "score",
"$playerUid": {
...
}
}
}
}
这将使您的数据在数据库中排序,因此当您检索它时,您将准备好所有数据。但请记住,如果您想要检索所有游戏和所有玩家,则意味着您将获取整个数据库。因此,您应该查看应用程序的需求,并重新考虑结构。
在缩放时可以提供帮助的是迭代游戏并使用firebase.database().ref(gameId).limitToLast(10)
检索有限数量的用户。
<强>更新强>
对于您的示例,您将拥有以下请求的所有游戏:
firebase.database().ref().once('value', snap => {
//prints all players for each game sorted ascending.
snap.forEach(game => {
game.forEach(player => {
console.log(player.val());
});
});
});
答案 1 :(得分:1)
尽管这个问题比较老,但可能有人(像我一样)在它上面绊脚石。特别是因为以问题作者的相似方式来构造数据库,以(例如)创建游戏排行榜系统非常直观。由于答案有点过时,因此我想添加一些内容。
前段时间,开发人员增加了深度嵌套孩子订购的可能性! (请参见Ordering by a specified child key)要这样做,您基本上必须做与作者完全相同的事情,并另外使用@adolfosrs给出的答案的第一部分。基本上,您必须做两件事:
.indexOn
(如@adolfosrs所述)OrderByChild()
命令。要使此工作在@steliosf给出的示例中进行,您必须执行以下操作:
首先在数据库规则中设置.indexOn:
{
"rules": {
"$gameId": {
".indexOn": "score",
"$playerUid": {
...
}
}
}
}
第二使用命令已经使用过的问题的作者:
rootRef.Child("root").OrderByChild("score")
我建议您始终添加一个LimitToFirst()或LimitToLast()命令,以避免拉动整个数据库,这可能是很多数据(当然取决于数据库的大小)。例如,要获得前10名得分,可以使用:
rootRef.Child("root").OrderByChild("score").LimitToLast(10)
由于数据是按升序排列的,因此您需要使用LimitToLast()。