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

Firebase queryOrderedByChild() method not giving sorted data

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

{
  "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

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

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

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

key: alovelace, value: Optional({ name = Ada Lovelace; score = 4; })

key: eclarke, value: Optional({ name = Emily Clarke; score = 5; })

快照会将内容return作为本机类型。 数据类型 returned:

  • NS 词典
  • 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"])
    }
})

Optional(2)

Optional(4)

Optional(5)

另外,实时数据库默认return一切都是升序

如果你想要降序,你可以在你的数据库中做一些tricks(4:40)。

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

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

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

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

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

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)
}

输出为:

ghopper

alovelace

eclarke

这是按分数升序排列的用户。

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

以上代码按升序获取最高的20个分数。没有 API 呼叫 return 他们以降序得分。

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

如果你真的坚持在客户端反转它们,你可以添加一个反转的分数。有关示例,请参阅