Firebase queryOrderedByChild()方法不提供已排序的数据

ilv*_*vcs 2 ios firebase swift firebase-realtime-database ios9

我的数据库结构是这样的:

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "score": 4,
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}
Run Code Online (Sandbox Code Playgroud)

我试图按降序检索前20个分数.

let queryRef = FIRDatabase.database().reference().child("users").queryOrderedByChild("score").queryLimitedToLast(20)
queryRef.observeSingleEventOfType(.Value, withBlock: { (querySnapShot) in
      print(querySnapShot.value)
})
Run Code Online (Sandbox Code Playgroud)

我想要输出像

score": 4
score": 3
score": 2

or 

score": 2
score": 3
score": 4

or 

2
3
4
Run Code Online (Sandbox Code Playgroud)

请让我知道如何解决这个问题.

Fra*_*len 7

当您按特定顺序请求子项时,生成的快照将包含与查询匹配的数据以及有关您请求它们的顺序的信息.

但是当您请求.value快照时,键+数据将转换为Dictionary<String,AnyObject>.由于字典没有额外的位置来放置有关订单的信息,因此在转换为字典时该信息会丢失.

解决方案是不要过早地转换为字典而是循环遍历快照:

queryRef.observeSingleEventOfType(.Value, withBlock: { (querySnapShot) in
    for childSnapshot in querySnapShot.children {
        print(childSnapshot.value)
    }
})
Run Code Online (Sandbox Code Playgroud)

你也可以听取这个.ChildAdded事件,而不是.Value在这种情况下孩子们会以正确的价值到达:

queryRef.observeSingleEventOfType(.ChildAdded, withBlock: { (childSnapshot) in
    print(childSnapshot.value)
})
Run Code Online (Sandbox Code Playgroud)

更新

我刚刚将这个JSON添加到我的数据库中:

{
  "users" : {
    "alovelace" : {
      "name" : "Ada Lovelace",
      "score" : 4
    },
    "eclarke" : {
      "name" : "Emily Clarke",
      "score" : 5
    },
    "ghopper" : {
      "name" : "Grace Hopper",
      "score" : 2
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后运行此代码:

let queryRef = ref.child("users").queryOrderedByChild("score").queryLimitedToLast(20);
queryRef.observeEventType(.ChildAdded) { (snapshot) in
    print(snapshot.key)
}
Run Code Online (Sandbox Code Playgroud)

输出是:

ghopper

alovelace

eclarke

哪个是按升序排列的用户.

更新以添加有关按降序获得分数的更多信息

上面的代码按升序排列得到20个最高分.没有API调用以降序返回它们.

但是逆转20个项目的客户端并不是性能问题,你只需要为它编写代码.例如,请参阅此答案.

如果您真的被迫在客户端进行逆转,则可以添加倒置分数.请参阅此答案以获取示例.


Wil*_*jay 5

使用方法observeEventType代替observeSingleEventOfType.另外,将FIRDataEventType设为ChildAdded.

最后,如果你想要前20项,请使用queryLimitedToFirst而不是queryLimitedToLast.

{
  "users" : {
    "alovelace" : {
      "name" : "Ada Lovelace",
      "score" : 4
    },
    "eclarke" : {
      "name" : "Emily Clarke",
      "score" : 5
    },
    "ghopper" : {
      "name" : "Grace Hopper",
      "score" : 2
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

对于上面的数据集

let queryRef = FIRDatabase.database().reference().child("users").queryOrderedByChild("score").queryLimitedToFirst(20)
queryRef.observeEventType(.ChildAdded, withBlock: { (snapshot) in
    print("key: \(snapshot.key), value: \(snapshot.value)")
})
Run Code Online (Sandbox Code Playgroud)

key:ghopper,value:可选({name = Grace Hopper; score = 2;})

key:alovelace,value:可选({name = Ada Lovelace;得分= 4;})

key:eclarke,value:可选({name = Emily Clarke;得分= 5;})

快照将返回内容作为本机类型.返回的数据类型:

  • 的NSDictionary
  • NSArray的
  • NSNumber(也包括布尔值)
  • 的NSString

所以,你可以这样得到你的分数.

    let queryRef = FIRDatabase.database().reference().child("users").queryOrderedByChild("score").queryLimitedToFirst(20)
queryRef.observeEventType(.ChildAdded, withBlock: { (snapshot) in
    if let scores = snapshot.value as? NSDictionary {
        print(scores["score"])
    }
})
Run Code Online (Sandbox Code Playgroud)

可选(2)

选购(4)

选购(5)

而且,实时数据库的默认值按升序返回所有内容.

如果你想降序,你可以在数据库中制作一些技巧(4:40).