我的应用程序有一个最高得分表,该表使用.queryOrdered(byChild:“ userHighScore”)和.queryLimited(toLast:100)来获得最高100分:
func getTopScores() {
var scores = [String]()
self.reference
.child("users")
.queryOrdered(byChild: "userHighScore")
.queryLimited(toLast: 100)
.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children.reversed() {
if let dataSnapshot = child as? DataSnapshot, let user = dataSnapshot.value as? [String:AnyObject] {
if let userHighScore = user["userHighScore"] as? Int {
var stringToAppend = "\(scores.count+1). "
if let userName = user["userName"] as? String {
stringToAppend += " \(userName) • \(userHighScore)"
}
scores.append(stringToAppend)
}
}
}
})
}
问题是当平局得分时。
理想情况下,第一个获得该分数的用户将高于表上具有相同分数的其他用户(而获得该分数的最新用户将是得分相同的用户中最低的)。
但是,该表以与Firebase Realtime数据库中出现的随机顺序相同的顺序显示得分相同的得分。
有没有办法按时间顺序对比分进行排序?
我已经为此花了好几个小时。预先感谢您的帮助!
答案 0 :(得分:6)
理想情况下,第一个获得该分数的用户将在表上具有相同分数的其他用户之上
您实质上是在尝试订购两个属性:userHighScore
和userHighScoreTimestamp
(我起了一个名字,因为您没有在问题中指定它)。 Firebase实时数据库只能查询单个属性。参见Query based on multiple where clauses in Firebase
您可以 做的是定义一个附加属性,该属性将高分值和已完成的时间戳相结合:
users: {
derenceUid: {
userHighScore: 42,
userHighScoreTimestamp: 1557695609344,
userHighScore_Timestamp: "000042_1557695609344",
},
dougUid: {
userHighScore: 31,
userHighScoreTimestamp: 1557609264895,
userHighScore_Timestamp: "000005_1557609264895",
},
pufUid: {
userHighScore: 42,
userHighScoreTimestamp: 1557695651730,
userHighScore_Timestamp: "000042_1557695651730",
}
}
通过这种结构,您可以通过以下方式获得得分最高的用户:
ref.queryOrdered(byChild: "userHighScore_Timestamp"). queryLimited(toLast: 1)
需要注意的一件事是,我将用户的高分填充为六位数。这是必要的,因为Firebase将对这些键进行字典比较,并且如果没有填充"5_1557609264895"
会比"42_1557695609344"
大。您必须弄清楚最高分数可以保留几位数。在我的示例中,我使用了6位数字,因此它最多可以保存100万个分数。
答案 1 :(得分:1)
理想地,您需要的是orderByChild两个值,分别是score和date。据我所知,Firebase实时数据库不支持该功能。我可以提出两种选择: