如何在列表中获取节点的索引/位置而不获取firebase中的完整列表?

时间:2016-06-14 12:52:36

标签: firebase firebase-realtime-database

我正在使用firebase为我们的手机游戏构建全球排行榜和社交排行榜。由于游戏将有高分数的1000个条目中的10个,因此不建议加载完整的条目列表,因此我们将使用分页。 但我想加载当前播放器的位置而不加载整个列表。

示例:排行榜有100名玩家,用户XYZ位于第65位。有没有什么方法可以在不加载整个列表的情况下获得65?

4 个答案:

答案 0 :(得分:1)

无需下载所有密钥,无法知道特定密钥的索引。它只是一个与Firebase的API不匹配的操作,主要是由于数据库的实时性。

答案 1 :(得分:1)

这不一定是一个简单的解决方案。如果您希望返回第n项,则此帖子可能有用:Can I get the nth item of a firebase "query"?

但是,你绝对可以在不使用orderBy和limitToFirst加载整个列表的情况下执行此操作,以返回前65位。像yourRef.orderByChild('points').limitToFirst(65)这样的东西。

可能不像你希望的那么简单,但我希望它有所帮助。

答案 2 :(得分:1)

这可能是一个非常简单的答案,但它实际上取决于您如何构建数据。

如果始终只有100个用户,并且您希望每个人从第65位到第1位,那很容易。

同样,如果您想要用户XYZ的位置,那也很容易。

还有一些方法可以按位置(或35)加载前2位用户

users:
   user_id_0
     position: 15
   user_id_1
     position: 32
   user_id_2
     position: 7

然后按位置排序查询/ users / position,然后queryLimitedToFirst(2)将返回user_id_2和user_id_0。

编辑:

根据更多数据,这里有几个选项。鉴于我们有5个用户,每个用户都有一个分数(我在列表中注明了他们的“位置”)

uid_0: 50 //pos 2
uid_1: 25 //pos 1
uid_2: 73 //pos 4
uid_3: 10 //pos 0
uid_4: 58 //pos 3

如果你想知道这个位置,根据uid_2的分数 - 我不知道你的平台,所以我会给出一个通用的流程:

步骤1)查询uid_2获得他的分数,73,然后

步骤2)queryOrderedByChild(得分).startingAtValue(73),获得分数从73到最高得分的节点

步骤3)然后结果将出现在快照中,因此请检查snapshot.childrenCount,它将是uid_2的位置,即4。这将减少加载的节点数。

缺点是列表越远,加载的数据就越多。如果你只有1000个节点,其中只有几个分数,那就不是很多数据了。

以下解决方案避免了大量数据,但需要应用程序进行更多工作。

当然,如果你的平台支持数组,这是一个超级简单的任务。使用上面相同的结构,将子项加载到数组中,并获取您想知道其位置的uid的索引号。

Swift代码

let ref = self.myRootRef.childByAppendingPath("scores")
ref.queryOrderedByValue().observeEventType(.Value, withBlock: { snapshot in

     var myArray = [String]()

     for child in snapshot.children {
          let key = child.key as String
          myArray.append(key)
     }

     let pos = myArray.indexOf("uid_0")
     print("postion = \(pos!)")
})

答案 3 :(得分:0)

一种方法可能是运行一个更新每个玩家的“Rank”属性的进程。它不会让他们立即访问他们当前的排名,但如果您对每天更新或定期更新的想法感到满意,那么这可能是一个有效的解决方案,不需要将大量数据返回给用户随着用户群的增长而增长。获取第n个项目的过程可能类似于@pufs:

var ref = new Firebase('https://yours.firebaseio.com/users');
var lastKnownScore = null;
var firstQuery = ref.orderByChild('points').limitToFirst(100);
var newRank = 1;
firstQuery.once('value', function(snapshot) {
  snapshot.forEach(function(childSnapshot) {
    childSnapshot.update({ rank: newRank });
    lastKnownScore = childSnapshot.value();
    newRank++;
  });
});

while(lastKnownScore > 0) {
  var nextQuery = ref.orderByChild('points').startAt(lastKnownScore).limitToFirst(100);

  nextQuery.once('value', function(snapshot) {
    snapshot.forEach(function(childSnapshot) {
      childSnapshot.update({ rank: newRank });
      lastKnownScore = childSnapshot.value();
      newRank++;
    });
  });
}

如果您希望多个玩家拥有相同的分数或者可能拥有0分的玩家,则需要进行一些重构,但希望您能看到我得到的内容。如果您设置了定期运行此代码的流程,则可以使您的排名保持相对最新状态。