I'm trying to create a leaderboard using Firebase and show the username, highscore, region.

12,080

Solution 1

You should separate your user specific data from the leaderboards.

You have your users node in which your user's data under their unique user id. Then you also can create a leaderboards node and under the same unique user id, your leaderboard specific data. This way you won't have to fetch all the data at once only to know the user specific data.

The connection is the user id, that is the unique id, that your user is going to know, and retrieve his/her data by. The other players can just retrieve the leaderboards node by a query. You should also store some seemingly redundant data, for instance the username which you would both need for the user's node and for the leaderboards.

Don't forget to apply security rules, so the user can only write to his/her data.

Looking like this:

enter image description here

The authenticated user who knows his/her UID can then listen to his/her own leaderboard score by fetching data on this path: "leaderboards/UID" right.

Other players should just have to use the path: "leaderboards" to fetch every player on the leaderboard. To order them and only fetch the top 10 players you have to use queries.

Use queryOrderedByChild to order your data by highscore For this you should also add the security rule: ".indexOn": "highscore".

To fetch the top10 players use queryLimitedToFirst setting it to 10, it will only download the top 10 players.

You should read more about queries: https://firebase.google.com/docs/database/ios/lists-of-data#sorting_and_filtering_data

Solution 2

While using JSON the flatter the tree the better it is to

HighScore :{
  userID1 : 100,
  userID2 : 103;
  userID3 : 210;
   }, 
Users :{
  userID1 :{...}
  userID2 :{...}
  userID3 :{...}     
 }

If you want to add a different relational property to the user, just add another parent node for that particular user and query it.

FIRDatabase.database().reference().child("HighScores").observeSingleEvent(of: .value, with: {(Snap) in

        print(Snap.value)

    })

PS:- You can always play with security rules in firebase , to manipulate the permissions for specific node in the Database to your authenticated users Docs Link.

To append your data in firebase node:-

 FIRDatabase.database().reference().child("HighScores").observeSingleEvent(of: .value, with: {(Snap) in

        if let snapDict = Snap.value as? NSMutableDictionary{

            snapDict.setObject(_yourHighScore, forKey : FIRAuth.auth()!.currentUser!.uid as NSCopying)
            FIRDatabase.database().reference().child("HighScores").setValue(snapDict)
        }
    })

Solution 3

You can store everything under user node if you want. And fetch user details by applying sort based on high score. You should also apply limit.

If you are planning to create separate node for user details and score then you must fetch score from the score node and based on user id fetch user detail from user node.

Share:
12,080
bradford gray
Author by

bradford gray

Updated on June 05, 2022

Comments

  • bradford gray
    bradford gray almost 2 years

    My goal is to create a leaderboard using Firebase and to show the username, high score and region in a tableview. My current Database looks like this enter image description here

    I have everything under user at the moment. I did it this way so i could increment data for the current user. Unfortunately, by doing it this way, I don't think I can let others see someone elses high score or username. Is there a solution to this problem using the current node setup, or do I need to change it. And if so can someone give my examples of how the database should look.