Database Structure in Firebase - android

How can I create a structure where a game is link to 2 players? For example, if I create a ping pong game and after the game I want to keep the score and the players. How can I do that? How can I link the 2 players into one game and know what player won and which one lost?
I did something similar in SQL but I do not know how to do it in JSON (Firebase) for Android. In SQL, I created a users table and a games tables and I logged player 1 and player 2 with their user name and then do a SELECT with what player won and which one lose.
How can i do this in Firebase?
Thanks!

With NoSQL the data is flattened and duplicated where needed for quick access to relevant data. This is called denormalization which you can read up more in this great post.
So the ping pong game post you provided, your firebase JSON database might look something like this:
players: {
-KUQvO_GBh4jdale6Pj4: {
name: 'Hillary',
wins: 2,
lost: 0,
tied: 0,
gamesPlayed: [
-KUQvQhApOLfhl0yzTTH,
-KUQwI4P9q4DdSsUn9Du
]
},
-KUQvQ3_--kO67AOgc9D: {
name: 'Trump',
wins: 0,
lost: 2,
tied: 0,
gamesPlayed: [
-KUQvQhApOLfhl0yzTTH,
-KUQwI4P9q4DdSsUn9Du
]
}
},
games: {
-KUQvQhApOLfhl0yzTTH: {
player1: -KUQvO_GBh4jdale6Pj4,
player2: -KUQvQ3_--kO67AOgc9D,
winner: player1,
timestamp: 1476863790
},
-KUQwI4P9q4DdSsUn9Du: {
player1: -KUQvO_GBh4jdale6Pj4,
player2: -KUQvQ3_--kO67AOgc9D,
winner: player1,
timestamp: 1476863999
}
}
UPDATE
This article talks about multiple-location updates that allows you to make simultaneous updates to multiple paths to preserve data integrity. If you make each update individually, there is a chance that one or more might fail, which then means that your data might mean it's out of whack.

Related

Firebase realtime database --- Are nested singleValueEventListeners a bad practice?

In real time you can't do a single query across multiple rootnodes, so I was wondering if doing multiple queries (nested one after the other) is a bad practice? I understand this can be done in one query in firestore, but I am specifically using realtime for this portion of my app due to high number of user read/writes.
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//get Data from query one here
reference2.addListenerForSingleValueEvent(){
//get Data from query two here
reference3.addListenerForSingleValueEvent(){
//get Data from query three here
}
}
}
The alternative to doing multiple calls to read the corresponding entries from each reference, is to duplicate the data of the other entries under each reference.
It's a bit hard to reason in your abstract example, so let's pick a more concrete, simple use-case: a chat app. Say you have two-level entities: users, and chat messages. Each chat message is written by a user, and a user has a display name. In the most normalized data model this could be:
users: {
user1: {
name: "david s."
},
user2: {
name: "Doug Stevenson"
},
usere: {
name: "Frank van Puffelen"
}
},
messages: {
message1: {
message: "In real time you can't do a single query across multiple...",
uid: "user1"
},
message2: {
message: "In a very general sense, nested callbacks...",
uid: "user2"
}
message1: {
message: "The alternative to doing multiple calls...",
uid: "user3"
}
}
Now let's say that we have a use-case where we want to display the latest 10 chat messages, each with the name of the user who posted that message.
The above data works fine, but you will need to read the user names from the /users node, pretty much how you're doing now. This is known as a client-side join, and is quite efficient since Firebase pipelines the requests over a single connection.
You'd could deduplicate the lookup of the names using a cache, since the user names typically change much less frequently than the chat messages. This reduced the overhead since you're only loading each user's data once, but the code can get a bit verbose.
An alternative is to duplicate the minimal data that you need for your use-case. This means your data model would look like this:
users: {
user1: {
name: "david s."
},
user2: {
name: "Doug Stevenson"
},
usere: {
name: "Frank van Puffelen"
}
},
messages: {
message1: {
message: "In real time you can't do a single query across multiple...",
name: "david s.",
uid: "user1"
},
message2: {
message: "In a very general sense, nested callbacks...",
name: "Doug Stevenson",
uid: "user2"
}
message1: {
message: "The alternative to doing multiple calls...",
name: "Frank van Puffelen",
uid: "user3"
}
}
Now you can display the list of the latest 10 messages with a single read. The cost is that you use more storage, but typically storage should be considered cheap. The disadvantage in code is that you now need to write the duplicate data, which is more complex. And of course the duplicated data could get out of sync.
All above approaches are valid. Which one you pick depends on the use-cases of your app, your comfort level in duplicating data, and how much you personally value things like the amount of code, bandwidth consumption, etc. There is no one-size-fits-all answer, so you will have to make your own call.
For some great reading/viewing on the topic, see:
NoSQL data modeling
Firebase for SQL developers
How to write denormalized data in Firebase
Firebase data structure and url
some more of my answers on NoSQL questions
In a very general sense, nested callbacks is considered poor programming style. Casually speaking, it's called callback hell. As you get deeper into these callbacks, the code gets increasingly difficult to read and manage.
That said, if it works for you, go for it. You're the boss of your code. If it doesn't work for you, you can do searches to find strategies for avoiding this situation.

How to model a Firebase Database in UML diagrams?

I have a project in android so I decided to make a Quiz app, and I used Firebase in it.
But I also need to design UML diagrams for this project and I was wondering if I can do it since Firebase is a Table-less database.
The Firebase databases, be it its realtime database or the cloud firestore, are document-oriented NoSQL databases. There are indeed no tables, just collections of documents, where each document is a JSON-like structure, and documents could contain other embedded collections or documents.
In theory, each document in a collection could be completely different from all the others. In this case, an UML class-diagram would make no sense since classes suppose common properties and behaviors.
db.collection("ouch"): // Not recommended
[ {name: "Spiderman"},
{size: "XXL", item: "T-Shirt},
{date: "July 4 1776", event:"independence day"} ]
In practice, however, documents in a collection are in general a set of very similar objects, or at least related objects. May be one object of the set has a couple of properties more, or a couple of properties less. But they represent the same kind of things:
db.collection("users"): // example 1, small variations
[ { id: "AL", first: "Ada",last: "Lovelace"},
{ id: "JSMITH", last: "Smith", first: "Joe", lastLogin:"2021-07-10"} ]
db.collection("shopItems"): // example 2, more variations but common ground
[ { id: 123, type: "Book", title: "The definitive guide to Firebase", author:"L.Moroney", price: 34.23 },
{ id: 124, type: "Record", title: "Get lucky", artist: "Daft Punk", price: 16.20}
{ id: 125, type: "Shirt", brand: "Seidensticker", model:"Classic", size: "XL", color:"white", price: 65.00 } ]
In this case, you may perfectly use UML class diagrams, because UML is not table based, but class based:
A class represents a kind of things. In reverse engineering you'd usually start with the known collections.
Small structural differences between documents of a same kind would be represented in the UML class diagram either with "optional" properties (i.e. multiplicity [0..1]) (see lastLogin in the users example).
More substantial differences between documents having some common ground, would usually be modeeled with more specialized classes (see the shopItems example, where we can guess a class ShopItem and specializations thereof such as BookItem, RecordItem, TextileItem).
The challenge in the modelling, is to understand the embedded documents and sub-collections. These are often sign other associated classes (or composed classes).
In principle, the UML class-diagram would not be used only for the database (data only), but it would be used to design the objet model of your application (data and behavior) independently of your database. The model could then help you to design the database based on the kind of objects needed to address you' user's needs.

Firebase data flattening

I have a quick question about the best practices for data structure in a firebase database.
I want users of my app to be able to maintain a friends list. The firebase documentation recommends creating a schema (not sure if thats the proper word in this context) that is as flat as possible. Because of this I thought it would be a good idea to separate the friends section from the player section in the database like so:
{
"players":{
"player1id":{
"username":"john",...
},
"player2id": ...,
"player3id": ...
}
"friends": {
"player1id"{
"friends":{
"friend1Id":true,
"friend2Id":true
}
},
}
"player2id"{
"friends":{
"friend1Id":true,
"friend2Id":true
}
},
}
}
So my questions are as follows:
Is this a good design for my schema?
When pulling a friends list for one player, will the friends lists of EVERY player be pulled? and if so, can this be avoided?
Also, what would be the best way to then pull in additional information about the friends once the app has all of their IDs. e.g. getting all of their user names which will be stored as a string in their player profile.
Is this a good design for my schema?
You're already thinking in the right direction. However the "friends" node can be simplified to:
"friends": {
"player1id": {
"friend1Id":true,
"friend2Id":true
}
}
Remember that Firebase node names cannot use the character dot (.). So if your IDs are integer such as 1, 2, and 3 everything is OK, but if the IDs are username be careful (for example "super123" is OK but "super.duper" is not)
When pulling a friends list for one player, will the friends lists of EVERY player be pulled? and if so, can this be avoided?
No. If you pull /friends/1 it obviously won't pull /friends/2 etc.
Also, what would be the best way to then pull in additional information about the friends once the app has all of their IDs. e.g. getting all of their user names which will be stored as a string in their player profile.
Loop through the IDs and fetch the respective nodes from Firebase again. For example if user 1 has friends 2, 3, and 4, then using a for loop fetch /players/2, /players/3, and /players/4
Since firebase pull works asynchronously, you might need to use a counter or some other mechanism so that when the last data is pulled you can continue running the completion code.

Android, Json modifying element

I have a json file on server:
{"images":[
{"url":"...", "likes":"123"},
{"url":"...", "likes":"234"},
{"url":"...", "likes":"345"}
]}
I get the json file on android read it, but if someone likes a picture i want to change the value of the first picture from 123 to 124, is this possible and how can i do this?
The whole point is to change a json value on server,from client side.
Also if this isn't possible how can i make this happen?
Also if i want to get the Top50 rated pictures,how can i sort them and get only the 50 picture,without getting all pictures and sorting them on android ?
Which one is better,initializing the Top50 images,when the user starts the app,or when the user click on the button Top50.I assume that if its when he click the button,there might be some performance issues server side?
My other idea is to have a function server side,which every 10 min,executes automatically and gets the Top50 rated and makes something like json file.So it all happens server side automatically.
To make this happen, client should expose some interface, i.e. function that will allow to modify file on server side. The interface and implementation of this function greatly depends on server itself, i.e. which protocols it handles, what built-in or external modules it supports, which languages are supported, etc... For example, the classic scenario is using apache as HTTP server, CGI enabled, and write CGI function in perl. So, in this case interface would look like http://server.name/like.cgi?image=image123.
How to modify the values on the server ?
For this every like of a photo should be a post request of this sort.
{
"data": [
{
"image_id": 3133456,
"likes": 343
},
{
"image_id": 3133456,
"likes": 343
}
]
}
On parsing this request server updates the corresponding image's like on the server.
How to get the top 50 rated/liked images from the server ?
Again you send a get request to such a url
http://server.getsomething.com/getTop50Images
On server side
On receiving such a request you make a query on the table in your database something like this
select image_id , image_url, likes from image_table limit 50 ORDER BY likes ASC
Now getting those query results and returning them as a json would not be a performance hit until you have huge bulk of data. like some million rows may be in your database.
Response can be something like this
{
"result": [
{
"image_id": 3133456,
"likes": 34400,
"url": "http://flickr.com/someimage"
},
{
"image_id": 3133456,
"likes": 34380,
"url": "http://flickr.com/someimage"
}
]
}
You still avoid using a database yourself but can lease it from clouds services like parse.
However if you won't be using those services then you can take a look at ftp packages for js. Like the neo JavaScript library by apache.
But still a good choice will be to go with the database approach (is quiet simpler).

How Should I Store Data for My Android App?

I'm quite new to Android programming (very little programming experience). I want to make an app that will track Car maintenance. I would like users to be able to see their data (roughly) according to the following hierarchy:
Year (see total costs, maybe summarize categories)
--Month (month's costs)
----Maintenance Instance
------Details about the instance (what was done for what cost)
I don't have my data design finalized, but you can see the kind of data I'm trying to track. What approach would you suggest? Do I need to use SQLite? If so, would you recommend a hierarchy of tables or just one table that will be shown hierarchically through queries? Like I said, I'm new. I'd appreciate any pointers in the right direction.
In Android, you can use SharedPreferences to store simple data like global preferences (i.e. in your app you could store a currency flag as a preference to display currency as dollars or pounds) but for anything more complicated you should use SQLite. This tutorial is excellent and will get you started - http://www.vogella.com/tutorials/AndroidSQLite/article.html It seems like you could have one table with each row being a maintenance entry with columns for the date, cost and action carried out. You could then query the database by a date range to get the cost for that range or a list of action carried out in that range (e.g. per month or year). Each row would represent a separate maintenance event.
I recommend you use JSON, a very easy to use storage format. A typical JSON message you would store might look like the following:
{
"maintenance_data": [
{
"date": 1091029109,
"maintenance_details": "Drove car around while owner was gone"
},
{
"date": 1021234134,
"maintenance_details": "Ate cookies while on job"
},
{
"date": 1041023234,
"maintenance_details": "Ain't nobody got time for maintenance"
}
],
"car_id": 1234,
"owner_name": "Slick diddy"
}

Categories

Resources