Search code examples
iosswiftfirebaseios9firebase-realtime-database

Firebase queryOrderedByChild() method not giving sorted data


My database structure is some thing like this:

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

I am trying to retrieve top 20 scores in descending order.

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

i am trying to get output like

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

or 

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

or 

2
3
4

Please let me know how to solve this.


Solution

  • Use method observeEventType instead of observeSingleEventOfType. Also, make FIRDataEventType to ChildAdded.

    Last, If you want Top 20 items, use queryLimitedToFirst instead of queryLimitedToLast.

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

    For the dataset above

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

    Snapshot will returns the contents as native types. Data types returned:

    • NSDictionary
    • NSArray
    • NSNumber (also includes booleans)
    • NSString

    So, you can get your scores this way.

        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)

    Moreover, the default of realtime database return everything in ascending order.

    If you want descending order, you can make some tricks(4:40) in your database.