ShintoTuna
ShintoTuna

Reputation: 3787

Firebase database structure suggestion

I am just staring off with firebase and with NoSQL in general and I came across an issue with data structuring for best usage of the application.

I have an application for saving results of 4 player foosball (table soccer) games. Each player has hes own rating and after each game the rating is recalculated. Also there are individual game results (goals, own goals) and player positions saved each game. I have 2 main views in the app - Game View where i insert game results and Ratings view where i have a scoreboard of players ranked by their rating and avg goals scored.

At the moment I have the following structure:

// players
{
   "playerID": {
       firstName: string,
       lastName: string,
       ratings: {
           overall: { mu: string, number: string }
       }
   }
}

// games
{
   "gameID": {
       participants: {
           "HOME_DEF": {
               playerID: string,
               firstName: string,
               lastName: string,
               ratings: { overall: { mu: string, number: string } }
               adjustedRatings: { overall: { mu: string, number: string } }
               goals: number,
               ownGoals: number,
           },
           "AWAY_DEF": { ... },
           "HOME_OFF": { ... },
           "AWAY_OFF": { ... },
       }
       time: elapsedTime,
   }
}

With this I am saving every game as an object and recalculate the ratings with Cloud Function on game onCreate event. From what I read during the onCreate event I can not access other nodes (like players) so I can not update players rating.

I have 2 questions:

  1. What would be necessary to adjust this schema so I could easily update data for player rating and have it available for views?

  2. How could I calculate avg goals scored and save it in players object?

Upvotes: 1

Views: 449

Answers (2)

TheBen
TheBen

Reputation: 3520

First some considerations on the structure of your database read this and also you may find this youtube series useful if you know SQL database. here I share a few points though.

1.Try to keep your database as shallow as possible, i.e, avoid deep nesting of your data.

2.structure your data such that a user is downloading only what they need. Now keep in mind, firebase charges per read/write so there is a fine line here to optimize your costs vs what user is paying for data. But that shouldn't really be a concern as long as your app is not dumping huge amount of data.

For calculating your average score, you need to write a Firebase function (samples) that is triggered everytime scores change and calculates a new average and writes it back to database. So let's say there are some users and their scores saved in a node like below:

users_goals: {
    user1: 
        goals: 5
    user2: 
        goals: 5
    user3: 
        goals: 5
    ...
    ...
}

Your function is going to look like

calcul_average : functions.database.ref('/users_goals/{USER}').onWrite(event => {
.... get data from event i.e, const data = event.data; 
.... AVERAGE CALCULATION LOGIC
.... then upload the average to where you want in database like this:
   admin.database().ref(`/location_you_want_to_save/${userId}/average`).set(your_calculated_average); 

},

and that's it as long as concurrency is not an issue. If average can be changed by multiple users at the same time then you would need to use transactions to write your data. Calculating the average depends on your game logic of course and you have to make sure it's the write average.

Again, keep in mind to avoid deep nested structure in your database. It's better to spread your data, well not too too shallow though. I would go with max 3 folds and after that things can get messy or you are downloading a lot of not needed data per each query, client side. Cheers

Upvotes: 1

Grimthorr
Grimthorr

Reputation: 6926

The Firebase Admin SDK is available within Cloud Functions, which can give you access to other locations and nodes in the database:

// The Firebase Admin SDK to access the Firebase Realtime Database. 
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

With this, you could access the players/ratings node with something like:

var db = admin.database();
var ref = db.ref("players/" + playerId + "/ratings");

And then make any read/write operations that you require, so you may not need to change your database structure.

Upvotes: 1

Related Questions