How to properly use queryOrderedByValue

advertisements

I have this function written in Swift that fetch the leaderboard and then shows it to the user :

@IBAction func onShowLeaderboardTapped(_ sender: Any) {
        let leaderboardDB = FIRDatabase.database().reference().child("scores").queryOrderedByValue().queryLimited(toLast: 5)

        leaderboardDB.observeSingleEvent(of: .value, with: { (snapshot) in
            print("leaderboard snapshot:" ,snapshot)
        }, withCancel: nil)

    }

The problem is that when I fetch it, it gaves me the following list :

 Ben = 9;
 Gabriela = 12;
 Ivailo = 7;
 Petar = 10;
 Vania = 10;

It shows me the first five players, but then it lists them alphabetically. Since this is not a big problem I wonder if there is a way to order them by the value.

These are the rules:

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null",
      "scores": {
      ".indexOn": ".value"
    }
  }
}

And the DB is organized as follows:

  matchrooms:
  users:
  scores:
>      Ben: 9
>      Dimitar: 7
>      Gabriela: 12
>      Ishest: 6
>      Ivailo: 7
>      Ivan: 5
>      Marina: 3
>      Pesho: 3
>      Petar: 10
>      Rosen: 6
>      Vania: 10
>      Yasen: 2

So, my question is how to properly use the queryOrderedByValue() to retrieve the first five players and list them by the points they've scored?


When you fire a query against Firebase, it returns the keys of the items that match your query, the value of those items and the relative order of the items in the result. If you listen for a .Value event, all three of these are combined into a single FIRDataSnapshot.

But when you then either ask for the value property of that snapshot or print that snapshot as one block, the data is converted into a Dictionary. Since a dictionary can only contain keys and values, the ordering of the items is lost at that point. And as it turns out, the dictionary then prints the items ordered by their key.

To get the items in order, you should iterate over them using snapshot.children:

leaderboardDB.observeSingleEvent(of: .value, with: { (snapshot) in
    for child in snapshot.children {
        print(child.key)
    }
}, withCancel: nil)

Also see:

  • Firebase snapshot.key not returning actual key?
  • Firebase getting data in order
  • Firebase queryOrderedByChild() method not giving sorted data