Firebase数据库结构建议

时间:2017-11-08 20:40:13

标签: firebase firebase-realtime-database

我只是盯着firebase和NoSQL,我遇到了数据结构问题,以便最好地使用该应用程序。

我有一个保存4人桌上足球(桌上足球)比赛结果的申请。每个玩家都拥有自己的等级,每次游戏后都会重新计算等级。每场比赛还有个人比赛结果(进球,自己的进球)和球员位置。我在应用程序中有2个主要视图 - 游戏视图,其中我插入游戏结果和评级视图,其中我有一个按其评分和平均目标得分排名的玩家记分牌。

目前我有以下结构:

// 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,
   }
}

有了这个,我将每个游戏保存为一个对象,并在游戏onCreate事件中使用Cloud Function重新计算评级。从我在onCreate事件中读到的内容中我无法访问其他节点(如播放器),因此我无法更新玩家评级。

我有两个问题:

  1. 调整此架构有什么必要,以便我可以轻松更新玩家评分数据并将其用于观看?

  2. 我如何计算得分的平均目标并将其保存在玩家对象中?

2 个答案:

答案 0 :(得分:1)

云端功能中提供了Firebase Admin SDK,可以访问数据库中的其他位置和节点:

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

通过这种方式,您可以使用以下内容访问players/ratings节点:

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

然后进行所需的任何读/写操作,因此您可能不需要更改数据库结构。

答案 1 :(得分:1)

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