【问题标题】:Firebase queryOrderedByChild() method not giving sorted dataFirebase queryOrderedByChild() 方法不提供排序数据
【发布时间】:2016-08-30 08:11:30
【问题描述】:

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

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "score": 4,
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}

我正在尝试按降序检索前 20 个分数。

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

我正在尝试获得类似的输出

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

or 

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

or 

2
3
4

请告诉我如何解决这个问题。

【问题讨论】:

    标签: ios swift firebase ios9 firebase-realtime-database


    【解决方案1】:

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

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

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

    queryRef.observeSingleEventOfType(.Value, withBlock: { (querySnapShot) in
        for childSnapshot in querySnapShot.children {
            print(childSnapshot.value)
        }
    })
    

    您也可以收听.ChildAdded 事件,而不是.Value,在这种情况下,孩子将到达正确的值:

    queryRef.observeSingleEventOfType(.ChildAdded, withBlock: { (childSnapshot) in
        print(childSnapshot.value)
    })
    

    更新

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

    {
      "users" : {
        "alovelace" : {
          "name" : "Ada Lovelace",
          "score" : 4
        },
        "eclarke" : {
          "name" : "Emily Clarke",
          "score" : 5
        },
        "ghopper" : {
          "name" : "Grace Hopper",
          "score" : 2
        }
      }
    }
    

    然后运行这段代码:

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

    输出是:

    跳蚤

    爱丽丝

    埃克拉克

    用户分数升序排列。

    更新以添加更多关于按降序获取分数的功能

    上面的代码按升序获得了最高的 20 个分数。没有 API 调用以降序返回它们。

    但是在客户端反转 20 项是没有性能问题的,你只需要为它编写代码。参见例如this answer

    如果您确实在客户端反转它们,您可以添加反转分数。有关示例,请参阅 this answer

    【讨论】:

    • 嗨,对我都没有用。第一种方法抛出错误“不明确使用'value'”,第二种方法是打印未排序的值。score 不是用户的直接子节点。请注意“score”在每个用户的子目录中。
    • 嗨,我很抱歉问错了问题,我想要用户的前 20 分。我现在更新了问题。
    • 添加了一些链接解释和链接。
    【解决方案2】:

    使用方法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
        }
      }
    }
    

    对于上面的数据集

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

    键:ghopper,值:可选({ 姓名=格蕾丝·霍珀; 分数 = 2; })

    键:alovelace,值:可选({ 姓名=艾达·洛夫莱斯; 分数 = 4; })

    键:eclarke,值:可选({ 姓名 = 艾米莉·克拉克; 分数 = 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"])
        }
    })
    

    可选(2)

    可选(4)

    可选(5)

    此外,实时数据库默认按升序返回所有内容。

    如果您想要降序,您可以在数据库中创建一些tricks(4:40)。

    【讨论】:

    • 仍然得到未排序的结果。
    • 嗨,我很抱歉问错了问题,我想要用户的前 20 分。我现在更新了问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2016-10-20
    • 2021-11-28
    • 2014-05-24
    • 2015-06-07
    • 1970-01-01
    相关资源
    最近更新 更多