Building a social network using Firebase - android

I'm currently developing basic social network Android app for sharing images. Already have PHP/mySQL back-end but thinking about migrating to Firebase because of some features that I like (e.g. security, fast read/write).
So, I have users, posts, followers, likes, comments (like every other social network nowadays).
Long story short, I want to know if I'm getting this right.
According to this Firebase documentation and its example I should include unique keys from some JSON trees to others like this (example from documentation):
// An index to track Ada's memberships
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
// Index Ada's groups in her profile
"groups": {
// the value here doesn't matter, just that the key exists
"techpioneers": true,
"womentechmakers": true
}
},
...
},
"groups": {
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true,
"eclarke": true
}
},
...
}
}
Does this mean that I will have to include keys from posts, comments, followers etc. to my users tree like this:
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
"profileImage": "http://blabla.bla?xyzooqlL.png",
"about:" : "Exit light, enter night",
"country": "Neverland"
// Index Ada's posts in her profile
"posts": {
// the value here doesn't matter, just that the key exists
"post123": true,
"post234": true
},
// all comments this user wrote
"comments": {
"comment123": true
},
// all posts this user liked
"likes": {
"post123": true
},
"followers": {
"user123": true,
"user234": true
}
},
...
},
"posts": {
"post123": {
"image": "www.bla.bla/sadsadsa.png",
"description": "Hue hue hue",
"likes": {
"alovelace": true,
"ghopper": true,
"eclarke": true
},
"comments": {
"comment123": true,
}
},
"post234": {
"image": "www.bla.bla/233arweeq.png",
"description": "This is nice",
"likes": {
"eclarke": true
},
"comments": {
"comment234": true,
}
},
"comments": {
"comment123": {
"userId": "alovelace"
"text": "cool",
"date": "current"
}
},
...
}
}
Isn't it a little too much if I have for example 5000 followers, 2000 followings, 1500 post likes? When fetching user or any other object I will also fetch all its keys within that object. Imagine fetching 15 very active users with all this data.
If you have any suggestions how should I structure data, please let me know. Any kind of feedback will be useful.
Thanks.

Related

How to get full data from many to many relationship in firebase db android?

I have a class which is part of a school and this class has teachers and students, all of them has name and maybe has phone number , I want to get the full data for the classes
but firstly, could you advice me, what is the best for performance and maintaining from the following Dbs :
1st one
"schools":{
"school1":{
"class1":{
"name":"SC1",
"teachers":[{
"name":"T1"
}, {
"name":"T2"
}],
"students":[
{"name":"S1"},
{"name":"S2"}
]
}
}
.
.
.
.
.
.
.
}
and the 2nd
"school":{
"school1":{
"name":"SC1"
},
"school2":{
"name":"SC2"
}
},
"classes": {
"class1": {
"name": "C1"
},
"class2": {
"name": "C2"
}
},
"students": {
"student1": {
"name": "S1",
"phone":"123456789"
},
"student2": {
"name": "S2",
"phone":"123456789"
},
"student3": {
"name": "S3",
"phone":"123456789"
},
"student4": {
"name": "S4",
"phone":"123456789"
}
},
"teachers": {
"student1": {
"name": "T1",
"phone":"123456789"
},
"student2": {
"name": "T2",
"phone":"123456789"
},
"student3": {
"name": "T3",
"phone":"123456789"
},
"student4": {
"name": "T4",
"phone":"123456789"
}
},
"classes_enrollments": {
"class1": {
"teacher1": true,
"teacher3": true,
"student1": true,
"student2": true
},
"class2": {
"teacher2": true,
"teacher4": true,
"student3": true,
"student4": true
},
"class3": {
"teacher1": true,
"teacher2": true,
"student3": true,
"student4": true,
"student1": true,
"student2": true
}
},
"student_friends": {
"student1": {
"student2": true
},
"students2": {
"student1": true,
"student3": true
},
"students3": {
"student2": true
}
},
"teacher_friends": {
"teacher1": {
"teacher2": true
},
"teacher2": {
"teacher1": true,
"teacher3": true
},
"teacher3": {
"teacher2": true
}
}
and for the 2nd way how to get the full data for the class1: in which school and it's name and count of teachers and students and their names and phones
Thank you
I would mix those two.
For code simplicity and reading performance of individual class details, the 2nd scheme would indeed be messy. The 1st scheme would be better, but with some improvements.
Keep the teachers and students paths at root, just like in the 2nd scheme.
Add teacher_enrollments and student_enrollments path at root, to save the ids of the classes that each teacher/student is associated with.
Don't save class teachers and students as arrays inside classes, but use maps instead, similar to what you're saving in the root teachers and students path.
That way, when you edit a teacher from the root path, you can also get a list of all their associated classes (the ids) from the enrollments path, and do a multi-path update for these classes, to update the teacher/student details in each associated class.
If you have lots of data, you might want to maintain a separate path for class summaries, so that you can easily show a list of classes, without having to download the data for all included teachers and students (which would be present multiple times in all these classes).
When you delete a class, you would also want to do a multi-path update to delete all associated enrollments. If the total number of students and teachers is not too big, you can just delete the enrollments for ALL teacheres/students. If you have lots of teachers/students, you could keep your classes_enrollments path (but with intermediate teachers and students before the ids), so that you can make an update with only the required teacher/student ids. (it's actually a lot simpler. You already have the teacher/student IDs in the class info)
// How to delete a class in JavaScript.
// For Java, use updateChildren() instead of update(),
// and supply it with a HashMap instead of a plain object.
const classToDelete = { id: 'class1', teachers: ..., students: ..., school: ... };
const updateObject = {
['classes/'+classToDelete.id]: null },
['schools/'+classToDelete.school.id+'/classes/'+classToDelete.id]: null },
};
Object.keys(classToDelete.teachers).forEach(teacherId => {
updateObject['teachers/'+teacherId +'/classes/'+classToDelete.id] = null;
});
Object.keys(classToDelete.students).forEach(studentId=> {
updateObject['students/'+studentId+'/classes/'+classToDelete.id] = null;
});
dbRef.update(updateObject);
Example database structure (slightly different than instructed, but using the same concepts):
"schools": {
"school1": {
"id": "school1",
"name": "The best school",
"classes": {
"class1": {
"id": "class1",
"name": "The best class"
}
}
}
},
"classes": {
"class1": {
"id": "class1",
"name": "The best class",
"teachers": {
"teacher1": {
"id": "teacher1",
"name": "The best teacher",
"phone": "123"
}
},
"students": {
"student1": {
"id": "student1",
"name": "The best student",
"phone": "456"
}
},
"school": {
"id": "school1",
"name": "The best school"
}
}
},
"teachers": {
"teacher1": {
"id": "teacher1",
"name": "The best teacher",
"phone": "123",
"classes": {
"class1": {
"name": "The best class",
"school": {
"id": "school1",
"name": "The best school"
}
}
}
}
},
"students": {
"student1": {
"id": "student1",
"name": "The best student",
"phone": "456",
"classes": {
"class1": {
"name": "The best class",
"school": {
"id": "school1",
"name": "The best school"
}
}
}
}
}
Good luck!

Using Graph API , how to retrieve Images of the comments and replies to the comment?

I am creating an Android App.The App have a feature that retrieve Facebook posts using Graph API.
My Problem
My Problem is , the received JSON lacks the following fields:
Url for the images attached with the comments
Replies to the comments
Only No. of likes available. No Reactions list
For posts containing more than one images , full_picture fields contains link to only one image. Where is the link for other images ?
I used the /me/posts to get the posts.
Why I can't get the above details ?
Steps taken
I searched Stackoverflow but The answers only mentioned how to get images and replies for individual commment(by using comment id) , but no reference how to get it alongs with the JSON received from "/me/posts". (So , this is not a duplicate!!!!)
My Queries
Why I can't get the above details ?
What is the way to get comment's Images , replies,url for all images of the Parent post and Posts reactions in bundle.(that is along with the JSON of "/me/posts" without running /comment request for each and every comment?
My Code
Code the executes Graph Query
login_button.setReadPermissions(Arrays.asList(
"public_profile", "email", "user_birthday", "user_friends","user_posts", "user_status")); // Setting permissions
Bundle params = new Bundle();
params.putString("fields", "message,created_time,id,full_picture,status_type,source,comments.summary(true),likes.summary(true)");
params.putString("limit", "100");
new GraphRequest( loginResult.getAccessToken(), "/me/posts", params, HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
/* handle the result */
try {
EditText postsText = (EditText) findViewById(R.id.postText);
String res = response.toString();
res = res.replaceAll("\\{Response:\\s*\\w*\\W*\\s*[0-9]*\\W*\\w*:", "");
res = res.replaceAll("\\,\\s*error:\\s*null\\W*\\s*","");
postsText.setText(res);
writeToFile(res,"response");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
).executeAsync();
}
#Override
public void onCancel() {
txtstatus.setText("Login canceled");
}
#Override
public void onError(FacebookException error) {
txtstatus.setText("Login failed"+error.getMessage());
}
});
JSON
{
"data": [
{
"message": "'A reader lives a thousand lives before he dies. The man who never reads lives only one.'\n- George RR Martin",
"created_time": "2018-01-28T12:17:54+0000",
"id": "113326729482474_113029916178822",
"full_picture": "https://scontent.xx.fbcdn.net/v/t1.0-9/26993527_113029839512163_7617357733573673432_n.jpg?oh=c617cf94e3cdd62320fde60e445f760e&oe=5B22BC72",
"status_type": "added_photos",
"likes": {
"data": [],
"summary": {
"total_count": 0,
"can_like": true,
"has_liked": true
}
},
"comments": {
"data": [
{
"created_time": "2018-01-28T12:23:04+0000",
"from": {
"name": "Ragesh D Antony",
"id": "1845099915531898"
},
"message": "Such a wonderful Quote ..",
"id": "113029916178822_113036856178128"
},
{
"created_time": "2018-01-28T13:59:22+0000",
"from": {
"name": "Vignesh Lakshmanen",
"id": "1558536637578045"
},
"message": "Superb",
"id": "113029916178822_113251916156622"
}
],
"paging": {
"cursors": {
"before": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEV6TURNMk9EVTJNVGM0TVRJNE9qRTFNVGN4TkRJeE9EUT0ZD",
"after": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEV6TWpVeE9URTJNVFUyTmpJeU9qRTFNVGN4TkRjNU5qST0ZD"
}
},
"summary": {
"order": "chronological",
"total_count": 2,
"can_comment": true
}
}
},
{
"message": "\"It's an insane world, but in it there's one sanity, the loyalty of old friends. Friends, we must believe in one another.\" \n\n- Ben Hur",
"created_time": "2018-01-28T12:14:27+0000",
"id": "113326729482474_113026646179149",
"status_type": "mobile_status_update",
"likes": {
"data": [
{
"id": "1845099915531898",
"name": "Ragesh D Antony"
},
{
"id": "1558536637578045",
"name": "Vignesh Lakshmanen"
}
],
"paging": {
"cursors": {
"before": "MTg0NTA5OTkxNTUzMTg5OAZDZD",
"after": "MTU1ODUzNjYzNzU3ODA0NQZDZD"
}
},
"summary": {
"total_count": 2,
"can_like": true,
"has_liked": false
}
},
"comments": {
"data": [
{
"created_time": "2018-01-28T12:24:40+0000",
"from": {
"name": "Ragesh D Antony",
"id": "1845099915531898"
},
"message": "I like Ben Hur very much",
"id": "113026646179149_113040629511084"
}
],
"paging": {
"cursors": {
"before": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEV6TURRd05qSTVOVEV4TURnME9qRTFNVGN4TkRJeU9EQT0ZD",
"after": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEV6TURRd05qSTVOVEV4TURnME9qRTFNVGN4TkRJeU9EQT0ZD"
}
},
"summary": {
"order": "chronological",
"total_count": 1,
"can_comment": true
}
}
}
],
"paging": {
"previous": "https://graph.facebook.com/v2.11/113326729482474/posts?fields=message,created_time,id,full_picture,status_type,source,comments.summary%28true%29,likes.summary%28true%29&limit=100&format=json&since=1517141874&access_token=EAATh9tg5DMIBANl59BIPExJRzwZAhedH6PSsV2ZAO9FvzFiGqAW3HKafH9b7Bb0gSKnQMJktzUhX2DZCB29BezRUfI2HOumZAYp6FFYwOBJA1ZCdaE4ZCNLXB1ctUZBaKwbp8lXlZBwZBLLCG25CnGAckZClJXZA5omRDFtVvnJFTkJpqigUmy22QNGFmF4CgfC6sWEuVin7mAI9WZCkKkNVzSEeDGDoitt7xeVFiHXCetKOVoLZAl3qyfrYj&__paging_token=enc_AdC03uweQZCRZBN6tZCzhAQ50BZCKzx5koYtAZBRUmgY94TKcCrj6owvzXw9lpoL4iBKJUkW1ZAz4MoZAZBBaGSLZAHTHsKuEst7gtKaQrsQoiZBx8sO2QjQZDZD&__previous=1",
"next": "https://graph.facebook.com/v2.11/113326729482474/posts?fields=message,created_time,id,full_picture,status_type,source,comments.summary%28true%29,likes.summary%28true%29&limit=100&format=json&access_token=EAATh9tg5DMIBANl59BIPExJRzwZAhedH6PSsV2ZAO9FvzFiGqAW3HKafH9b7Bb0gSKnQMJktzUhX2DZCB29BezRUfI2HOumZAYp6FFYwOBJA1ZCdaE4ZCNLXB1ctUZBaKwbp8lXlZBwZBLLCG25CnGAckZClJXZA5omRDFtVvnJFTkJpqigUmy22QNGFmF4CgfC6sWEuVin7mAI9WZCkKkNVzSEeDGDoitt7xeVFiHXCetKOVoLZAl3qyfrYj&until=1517140875&__paging_token=enc_AdC1r6ZBwBybSmO16DuZCEWGDbdqTeiKCbTsa7h6WDenaZBgB40Xbc0flGcwYqiYPFiEf9wEvuBSoEvbfyl25J0JlbyfhKA1ZBufZC5ZAJMqLMg6bAXgZDZD"
}
}
Well, regarding "reaction list", this is available only for the Page owner (starting from 2018 Febraury).
Read the Graph API docs:
https://developers.facebook.com/docs/graph-api/reference/v2.12/post
"For Posts on a Page:
Any valid access token can read posts on a public Page, but responses will not include User information.
A Page access token can read all Posts posted to or posted by that Page, and responses will include User information."

How to select data from firebase realtime database

I have a database with a structure, roughly like
// An index to track Ada's memberships
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
// Index Ada's groups in her profile
"groups": {
// the value here doesn't matter, just that the key exists
"techpioneers": true,
"womentechmakers": true
}
},
...
},
"groups": {
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true,
"eclarke": true
}
},
...
}
}
But I can't figure out how to select users who are members of the same set of groups
You'd have to define an additional group_combinations or all_groups index, where you store each user under their combines the groups:
all_groups: {
"techpioneers_womentechmakers": {
alovelace: true
}
}

How to structure Firebase Database

I am using Firebase Database for my mobile and web application. I wanted to get advise for how to structure the JSON Tree. I have the following use case in mind:
Mobile app user logs in and gets all nearby restaurants in a list. User sets order on one restaurant. The restaurant owner uses web or mobile application to see incoming orders and accepts them. After accepting the order, the mobile app user gets response that his order has been accepted. Now my idea for the structure was the following:
SO we have one node at top level for each restaurant and each restaurant node contains a requests node which saves all the requests for this restaurants.
Is that structure ok or could this be structured better?
Consider a data structure like this, you don't want to retrieve all the request when you get a restaurant and this way, you can get all the requests for a restaurant and all the requests from a particular user.
{
"requests": {
"req1": {
"status": 0,
"time": 1473593287,
"user": { "u2": true }
},
"req2": {
"status": 0,
"time": 1473593227,
"user": { "u1": true }
},
"req3": {
"status": 0,
"time": 1473594287,
"user": { "u1": true }
},
"req4": {
"status": 0,
"time": 1473594227,
"user": { "u2": true }
},
},
"restaurant-requests": {
"resA": {
"req1": true,
"req2": true
},
"resB": {
"req3": true,
"req4": true
}
},
"restaurants": {
"resA": {
"name": "Example Restaurant A",
"address": "1 Example Street"
},
"resB": {
"name": "Example Restaurant B",
"address": "2 Example Street"
}
},
"user-requests": {
"u1": {
"req2": true,
"req3": true
},
"u2": {
"req1": true,
"req4": true
}
},
"users": {
"u1": {
"address": "123 Example Street"
},
"u2": {
"address": "124 Example Street"
},
},
}
That's what I would do..
good luck!

Firebase: How to avoid nested callbacks?

Based on the official Firebase documentation (https://firebase.google.com/docs/database/android/structure-data) it's suggested to structure data in this sort of a format:
// An index to track Ada's memberships
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
// Index Ada's groups in her profile
"groups": {
// the value here doesn't matter, just that the key exists
"techpioneers": true,
"womentechmakers": true
}
},
...
},
"groups": {
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true,
"eclarke": true
}
},
...
}
}
Here's my understanding of the callback flow (By callback I refer to onDataChange of addValueEventListener/addListenerForSingleValueEvent)
Callback for -groups-
....In a loop Callback for each of the members (to get details from -users- node)
........Another Callback if -users- has a field for which data is at a different node
And so on and so forth.
Can this sort of a structure lead to a nested callback scenario, if yes, how to avoid it ?

Categories

Resources