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

时间:2016-08-30 08:11:30

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

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

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

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

2 个答案:

答案 0 :(得分:7)

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

但是当您请求快照的.value时,密钥+数据将转换为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)
}

输出结果为:

  

ghopper

     

alovelace

     

eclarke

用户按升序排列。

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

以上代码按升序排列得分为20分。没有API调用以降序返回它们。

但是反转20项客户端并不是性能问题,你只需要为它编写代码。请参阅示例this answer

如果您真的被迫在客户端倒车,您可以添加倒置分数。有关此示例,请参阅this answer

答案 1 :(得分: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
    }
  }
}

对于上面的数据集

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;         得分= 2;       })

     

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

     

key:eclarke,value:可选({         名字= 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"])
    }
})
  

可选(2)

     

可选(4)

     

可选(5)

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

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