Firebase数据库按更深的子项排序

时间:2017-06-01 23:12:17

标签: firebase firebase-realtime-database

考虑Firebase数据库的以下结构:

    • 的Game1
      • $ playerUidA
        • 得分:50
      • $ playerUidB
        • 得分:10
      • .....
    • GAME2
      • $ playerUidC
        • 得分:20
      • $ playerUidD
        • 得分:30
      • .....
    • game3
      • .....

我想运行一个返回所有游戏节点的查询,其中每个游戏节点(玩家)的孩子将根据得分进行排序。游戏节点包含每个玩家的UID,并且每个UID节点包含玩家的得分。我也存储其他数据,但是,为了这个例子,我将只使用得分。

我可以使用一个查询执行此操作吗?就像是 rootRef.child("root").orderByChild("score")?不幸的是,这似乎不起作用。

或者实现这一目标的唯一方法是手动排序客户端上的项目?

@Puf - 希望你能回答:)

2 个答案:

答案 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给出的答案的第一部分。基本上,您必须做两件事:

  1. 使用.indexOn(如@adolfosrs所述)
  2. 使用OrderByChild()命令。

要使此工作在@steliosf给出的示例中进行,您必须执行以下操作:

首先在数据库规则中设置.indexOn:

{
  "rules": {
    "$gameId": {
      ".indexOn": "score",
      "$playerUid": {
        ...  
      }
    }
  }
}

第二使用命令已经使用过的问题的作者:

rootRef.Child("root").OrderByChild("score")

我建议您始终添加一个LimitToFirst()或LimitToLast()命令,以避免拉动整个数据库,这可能是很多数据(当然取决于数据库的大小)。例如,要获得前10名得分,可以使用:

rootRef.Child("root").OrderByChild("score").LimitToLast(10)

由于数据是按升序排列的,因此您需要使用LimitToLast()。