Query list from multiple countries in firebase - android

I wanted to try NoSql and started my project in Firebase. My app's data has increased a lot. However, now I need to run a country-specific app and hence show/filter data according to countries in my app.
The structure of my current data is as follows.
{ clients: {
"04E2LBixKoVn9sGzRvxtMoC7MsF3" : {
"clientName" : "Rising Mall",
"contact" : {
"branches" : {
"-Kx6QoVhr0WpDQ3i68_n" : {
"address" : "Test Location",
"phone" : "999999999",
"country": "USA"
}
},
"mail" : "test#test.edu.np",
"website" : "http://www.test.np"
},
"description" : "Test Description."}
},
"073ezb0UsgetSef0lwk50dhogjM2" : {
"clientName" : "Leather Craft",
"contact" : {
"branches" : {
"-Kx6QoVj_QKM7tjekh_1" : {
"address" : "Test Location",
"phone" : "888888888"
"country": "UK"
}
},
"mail" : "test#test.com",
"website" : "https://www.test.com"
},
"description" : "Test"
}
}
From the above structure, I want to get a list of all the clients whose country is "USA". How can I do it directly by querying FirebaseDatabase in Android? Is it possible? Or do I have to change the structure of my database completely? If I have to restructure my database do suggest a solution to that as well.
UPDATE
I took the suggestion given by #alex-mamo and designed all my structures by denormalizing the data.
Firebase-root
|
--- usClients
|
--- usClientId1 : true
|
--- usClientId2 : true

To achieve this, you don't need to restructure your database entirely, you just need to change it a little bit. To solve this problem, you need to add another node to your database named usClients. Every time you add a new user which is from USA, add it also in this new created node. Your new node should look like this:
Firebase-root
|
--- usClients
|
--- usClientId1 : true
|
--- usClientId2 : true
Whith this structure you can query your database to get only the clients within USA. This can be done attaching a listener on usClients node and iteration on the DataSnapshot object.
This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, i recomand you see this video, Denormalization is normal with the Firebase Database.

Related

(Android) Is there a simple way in Firebase Database to get a node's position ranked by a child?

Suppose I have a Firebase database in my Android App and structured as below:
{"firebase_db" : {
"users" : {
"user_uid_0" : {
"name" : "name_0",
"score" : 2000
},
"user_uid_1" : {
"name" : "name_1",
"score" : 3000
},
"user_uid_2" : {
"name" : "name_2",
"score" : 1000
},
"user_uid_3" : {
"name" : "name_3",
"score" : 4000
},
"user_uid_4" : {
"name" : "name_4",
"score" : 0
}
}
}
}
and I would like to sort them by the child "score". However, I do not want an entire list as the return (which can be easily achieved using the orderByChild() and limitToLast() methods). Instead, I want to know at what place a specific node is when ranked by the child "score" in descending order. For example, if I give the input "user_uid_0", then it should return 3 (the 3rd place); if the input is "user_uid_2", then it should return 4 (the 4th place)
But, I could not find a way to achieve this in several lines of code. Until now, the only way I've come up with to solve this problem efficiently was write a cloud function on Firebase... Is there any simpler way to do this?
Yes, you can solve this on user side. The simplest way I can think of is to query the database according to your needs to get all user objects. Add all this objects to a map, in which the key of the map is the user id and the value is the position. In the end, just iterate over the map and get the position according to your user id. That's it!

Firebase Database Querying: return latest added object in which the child has a value

I'm building an Android application in which the user can track its weight and progress by inserting their weight (optional) AND/OR upload a picture (optional).
{
"users" : {
"5aHvYy5wTIVAAgdOEso0wr2woHS2" : {
"firstName" : "Justin",
"logs" : [ {
"date" : "16/05/2018",
"progressPicture" : "http://www.google.com/example.jpg",
"weight" : 82.1
}, {
"date" : "17/05/2018",
"progressPicture" : "http://www.google.com/example.jpg"
}, {
"date" : "18/05/2018",
"weight" : 80.3
} ]
}
}
I have managed to get the latest log by ordering by key and limiting the result to 1, using the following code.
firebaseDatabase.getReference(USER_REFERENCE).child(firebaseAuth.currentUser?.uid).child(LOG_REFERENCE).orderByKey().limitToLast(1).
As can be seen from my JSON, a log doesn't necessarily have to have a weight value.
MY QUESTION:
How can I adjust my query so that I'll retrieve my latest log (so 1 log only based on key) where there is a value for weight?
You can add new entry called weight_log,which will be updated once new weight is recorded , you can do it easily with firebase functions that will be triggered on each
/users/{userId}/weight_log/{iterationID} create event
Then you can use limitToLast(1) on the new path
Generally it is good practice to flattening your data structure
From reading the wiki you can only filter the data and check if there's a value for weight by adding a ValueEventListener() which will return a list of all the list where you have to loop through it and get you value
https://firebase.google.com/docs/database/android/lists-of-data#filtering_data

Skip Row in FirebaseRecyclerAdapter

"news" : {
"-KnLRSIOyD7HgldFGty" : {
"caption" : "some grounds",
"content" : "some contents",
"created_on" : 1498246403444,
"newspaper_id" : "-KnLPu2N5039ZbqS",
"status" : false,
"thumbnail" : "thumbnail/1498254125498",
},
}
"newspapers" : {
"-KnLRSIOyD7HgldFGty" : {
"logo" : "logo/1498245996906",
"paper_name" : "NewsOnline"
},
}
I want to filter firebase to do something like this.
mDatabaseRef.child("news").orderByChild("newspaper_id").equalTo(id).orderByChild("status").equalTo(false);
Since multiple orderBy() will throw exception in firebase, what is the other way to achieve the filter.
Currently Firebase supports only a single orderBy per query.
So if you want to filter or order the results on more than one property (2 query in your case), you'll either have to do the additional filtering (or ordering) client-side in your Android code or you'll have to come up with your own indexing scheme that combines the properties.
In your case i suggest you add a new child named newspaperId_status which can get the value as concatenation of both values like this:
newspaperId_status: -KnLPu2N5039ZbqS_false
In this way you can query all newspappers which have the status of false.
Hope it helps.

How to retrieve multiple list of data from firebase

I've been searching for different examples but unable to find proper solution for my firebase nodes. I have 3 nodes 1 for Question ,Second node contains Answers of questions and 3rd node contains Comments on that Answer.!
How I will be Able to perform query using firebase
I've been searching for different examples but unable to find proper solution for my fire base tables. I have 3 nodes
Questions
Answers
Comments on Answers
How I will be Able to perform query using firebase (Join based Concept Implementation)
mdatabaseReference.child("Answer").equalTo(QID);
how I will be able to get Answers of specific Question and Comments on that Answers.!
here is My JSON
{
"Answer" : {
"f40357b1-d1f5-4b7a-98ec-54d9e7b2e518" : {
"dateTime" : "16 Mar 2017 15:30:29",
"professorAnswer" : "Hezbollah is an Islamist religious organization founded in 1985 and based in Lebanon. It follows Shi'Islam (also called Shi'ite Islam), the second largest denomination of Islam. Shi'a Muslims follow the teachings of the prophet Muhammad, a direct descendant of Isma'il (the first son of Ibrahim/Abraham).Contd.!",
"professorId" : "7ceef713-eb59-4db4-a8d2-21d5a01eedfc",
"questionId" : "fd2a34a0-e7d9-4b2c-8192-59705df827c2"
}
},
"comment" : {
"29192e3a-a013-4fcc-9859-1f5cc62464cb" : {
"commentText" : "ORGANIZATION hezbollah bases on the bible but their goals is to save people in pagans work!",
"dateTime" : "16 Mar 2017 15:30:52",
"AnswerId" : "f40357b1-d1f5-4b7a-98ec-54d9e7b2e518"
"questionId" : "fd2a34a0-e7d9-4b2c-8192-59705df827c2",
"userId" : "bXCeW6jfidbHuMCCCMkDGWcGZRS2"
}
},
"questions" : {
"41c454a8-fab6-4e41-9093-b1120ffd1be0" : {
"description" : "I know they're a Islamic organization but where are they based? What are their goals?",
"idQuestion" : "fd2a34a0-e7d9-4b2c-8192-59705df827c2",
"time" : "16 Mar 2017 15:30:12",
"title" : "What are the aims of the religious organization Hezbollah?",
"user_id" : "bXCeW6jfidbHuMCCCMkDGWcGZRS2",
}
},
"user" : {
"13bd37e5-fc87-4468-a89e-7cb4ecaab05f" : {
"email" : "email#gmail.com ",
"user_id" : "bXCeW6jfidbHuMCCCMkDGWcGZRS2"
}
}
The problem is that I want to filter those events... like for example, using .orderByChild("Answer").equalTo(QID) maybe it's wrong query but it is just for concept to get just the Answers for a given Question ID and then populate my List with it.
The right way to do this is to get every data separately, I don't know perfectly how your data are organized but this may be an appropriate solution:
// Gets the Question with id = QID
mdatabaseReference.child("Questions").child(QID);
// Gets the Answers for that question
mdatabaseReference.child("Answers").child(QID).once("value", function(answers) {
// For every Answer gets the comments
for(var answerID in answers) mdatabaseReference.child("Comments").child(QID).child(answerID);
});
EDIT: To use Firebase efficently you should structure your data depending on how you want to retrieve them. If you want to get all the answers for a given question I suggest you to use this data structure:
{
"Answers": {
"questionID": {
"answerID": {
"dateTime" : "16 Mar 2017 15:30:29",
"professorAnswer" : "Hezbollah is an Islamist religious...,
"professorID" : "...",
"questionID" : "..."
}
}
}
}
so that you can get your data for a given questionID this way:
mdatabaseReference.child("Answer").child(questionID).once('value', function(answers) {
// answers contains all the answer for the question with ID == questionID
});
NOTE: You don't have tables in Firebase, everything is JSON Object
There In No Concept of Joins In fireBase.Its noSql ..All you need to do is Query On According to Question Id and then in answer id check for question id..and same thing goes for comments it will be a nested EventBased search.!

Firebase Data Structure for shared data

I'm writing an Android app which uses Firebase realtime database. It's the first time I've used any Firebase products so it's been quite a learning curve so far, with already multiple data structure changes as the app develops and I learn more best practice.
I understand I should avoid nesting data wherever possible so at the moment I have my data stuctured like so;
{
"projects" : {
"jyZdNutWvUbA4XrQ3Gbb17rByyA2" : {
"-KcAq7Cx7wQL99_3Jo9l" : {
"area" : "R",
"dateCreated" : 1486257427801,
"dateModified" : 1486257427801,
"latitude" : 999.9,
"location" : "R",
"longitude" : 999.9,
"weather" : "R"
},
"-KcAqACaNOHSELyNfSu4" : {
"area" : "A",
"dateCreated" : 1486257440065,
"dateModified" : 1486257440065,
"latitude" : 999.9,
"location" : "A",
"longitude" : 999.9,
"weather" : "A"
}
}
}
}
I have a projects node which will store all the project data, then the unique userid child nodes (only 1 user in the above snippet) where each users projects are stored, then the unique projectid (2 projects in the above example) and finally all the details of a specific project. The idea being the app will just need to nvaigate to the apllicable userid and pull all children from there.
I have since decided I would like to add the ability to share a project with another user. I found this post (example code below if I implemented in my scenario) which seem's to do pretty much what I want, but I worry it will be less efficient as surely now I will need to scan all projects and dig an additional child deep (assuming I use the exact schema detailed below) before being able to check against rules as to whether a particular user is the owner or is allowed to read/write?
{
"projects" : {
"-KcAq7Cx7wQL99_3Jo9l" : {
"area" : "R",
"dateCreated" : 1486257427801,
"dateModified" : 1486257427801,
"latitude" : 999.9,
"location" : "R",
"longitude" : 999.9,
"weather" : "R",
"owner" : ""jyZdNutWvUbA4XrQ3Gbb17rByyA2",
"shares" : {
"uid" : "true"
}
},
"-KcAqACaNOHSELyNfSu4" : {
"area" : "A",
"dateCreated" : 1486257440065,
"dateModified" : 1486257440065,
"latitude" : 999.9,
"location" : "A",
"longitude" : 999.9,
"weather" : "A"
"owner" : ""jyZdNutWvUbA4XrQ3Gbb17rByyA2",
"shares" : {
"uid" : "true"
}
}
}
}
Additionally, many example data structures I have come across tend to store the data in a similar fashion to the second code snippet, i.e;
projects/projectid/userid whereas at the moment I have projects/userid/projectid which to me looks more efficient as you don't need to dig into each project to check if you have access to read/write. Am I misunderstanding the concept of how it works with my methodology?
The doubt the app is going to be huge with regards the database so I guess performance won't really be impacted that much regardless of my structure, but I do like to adhere to best practices wherever possible.

Categories

Resources