Firebase排行榜,最佳执行.SQL连接和顺序

Firebase Leaderboard, best Implmentation. SQL Joins and orderby

本文关键字:连接 顺序 SQL 执行 排行榜 最佳 Firebase      更新时间:2023-09-26

我正在创建一个使用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
      }
   }
}

谢谢

在NoSQL中,您经常按照您想要访问的方式对数据进行建模。我强烈推荐阅读这篇关于NoSQL数据建模的文章。

如果我对你的问题理解正确的话,你想要显示一个包含该组得分最高的用户的特定组的排行榜。对于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
});

我认为你的选择是正确的。对不起,改变你的数据周围一点,不知道你怎么能有两个键具有相同的名称(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
        });
    }
});