Firebase排行榜,最佳实施。 SQL连接和orderby

时间:2016-09-12 11:41:50

标签: javascript web firebase firebase-realtime-database

我正在使用Firebase作为数据库创建排行榜应用。我来自一个旧的学校SQL背景,所以这个新的noSQL类型的数据库给了我数据库密钥和参考焦虑。

如果我有组,每个组都有成员,然后所有用户都有各种测试的分数,那么获得给定测试分数按顺序显示的组的最有效方法是什么。在SQL中,使用连接然后命令显然是微不足道的,但到目前为止,在firebase文档中,我无法进行有效查询以获取连接数据块而无需在客户端进行某些排序工作

我目前的解决方案是,如下所示,但是在客户端进行所有排序似乎很痛苦。我目前获得该组的所有用户,然后迭代以获得每个用户的测试分数的各个记录。无论日期如何,我都需要获得给定测试的最高分。

var testName = 'test1';
var scores = firebase.database().ref('/groupMembers/' + 'TestGroup').once('value').then(function(snapshot) {
                console.log(snapshot.val());
                for(var user in snapshot.val()){
                    //...query the database for each separate users score on test1
                }
            //sort the test scores here on client side js
            });

数据库设计的任何提示都不会出错!

groupMembers{
   TestGroup{
       user1 : true
       user2 : true
   }
}

testScores{
   user1{
      test1{
         date : 11/04/2016
         score : 90
      }
     test1{
         date : 05/07/2016
         score : 100
      }
     test2{
         date : 11/06/2016
         score : 50
      }
   }
   user2{
      test1{
         date : 15/04/2016
         score : 70
      }
     test2{
         date : 05/07/2016
         score : 80
      }
     test2{
         date : 11/10/2016
         score : 50
      }
   }
}

由于

2 个答案:

答案 0 :(得分:2)

在NoSQL中,您经常根据您想要的方式对数据进行建模。我强烈建议您在NoSQL data modeling上阅读这篇文章。

如果我正确理解您的问题,您希望显示特定群组的排行榜,其中包含该群组的得分最高的用户。要使用Firebase查询,您可以使用此数据模型:

groupScores: {
  TestGroup: {
    user1: { // the highest score for user1
      test: "test1"
      date : 05/07/2016
      score : 100
    }
    user2: { // the highest score for user2
      test: "test2"
      date : 05/07/2016
      score : 80
    }
  }
}

所以你不会在这个模型中只保留每个用户的最高分,无论用户得到什么样的分数。这样每个用户只能在排行榜中出现一次。如果您的用例不同,则必须以不同方式对数据建模。

使用此数据结构,您可以获得排行榜:

var query ref.child('groupScores/TestGroup').orderByChild('score').limitToLast(10);
query.on('value', function(snapshot) {
  // TODO: loop over children, invert them, show leaderboard
});

答案 1 :(得分:1)

我认为你肯定会走正确的道路。很抱歉更改你的数据,不知道你怎么能有两个具有相同名称的键(第一个用户的test1和第二个用户的test2),但我会存储你的数据:

{
    groupMembers : {
        TestGroup : {
            tests : {
                test1 : true,
                test2 : true
            },
            users : {
                user1 : true
                user2 : true
            }
        }
    },
    userTestScores : {
        user1 : {
            test1 : true,
            test2 : true
        },
        user2 : {
            test1 : true,
            test2 : true
        }
    },
    testScores : {
        test1 : {
            users : { 
                user1: {
                    date : "11/04/2016"
                    score : 90
                },
                user2: {
                    date : "15/04/2016"
                    score : 70                  
                }
            }
        },
        test2: {
            users: {
                user1: {
                    date : "11/06/2016"
                    score : 50
                },
                user2: {
                    date : "05/07/2016"
                    score : 80              
                }
            }
        }
    }
}

然后您的查询将是在测试组中找到所有测试,然后您可以轻松找到最佳分数

firebase.database().ref('/groupMembers/TestGroup/tests').once('value').then(function (snapshot) {
    for (var test in snapshot.val()) {
        firebase.database().ref('/groupMembers/testScores/tests/' + test + '/users/').orderByChild('score').limitToLast(1).once('value').then(function (snapshot) {
            //highest score will be here
        });
    }
});