我正在使用firebase为我们的手机游戏构建全球排行榜和社交排行榜。由于游戏将有高分数的1000个条目中的10个,因此不建议加载完整的条目列表,因此我们将使用分页。 但我想加载当前播放器的位置而不加载整个列表。
示例:排行榜有100名玩家,用户XYZ位于第65位。有没有什么方法可以在不加载整个列表的情况下获得65?
答案 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分的玩家,则需要进行一些重构,但希望您能看到我得到的内容。如果您设置了定期运行此代码的流程,则可以使您的排名保持相对最新状态。