I have (somewhat) large list of jokes in my Firebase Database like in the image below.
I display them in a list in my Android app something like a feed. I also implemented possibility to log in with Firebase Authentication and now I want to add options for logged users to (dis)like jokes and add them to favorites (favorites are supposed to be like private bookmarks). I'm wandering how I could structure my data and I have two proposals:
Add new root node called "userJokes" with child nodes representing user UID from Firebase Authentication. Every UID child node should have copy of every joke from "joke" node with additional booleans representing (dis)like and favorite states.
Another solution is to add every user UID to a joke a user (dis)likes or adds to favorite.
First solution is logical, but how could I count number of likes and dislikes if I structure data this way? And what is the best way to copy every joke from "joke" node to "userJokes" node for every user to be showed in the feed? Second is impractical since while retrieving jokes, I will get info about every user that has (dis)liked or added to favorites and this is not what I need. Which solution is better? Is there any other? Is it OK to add user UID from Firebase Authentication to database in Firebase Database?
I think the first one is more accepted, although it needs some tweak :)
First note: if you create data only to be used as relational (like userJokes), it's better to just add simple value to it without copying entire source data (jokes data), like this:
userJokes: {
randomUserId: {
randomJokeId:true,
anotherRandomJokeId:true
}
awesomeUser: {
randomJokeId:true
}
}
Second note: if you want to implement two functionality (like and favorite), I think you should make it as different data. So it would be userJokeLike and userJokeFavorite (or something like that). And the structure for each of them should be same as I mentioned in first note.
In conclusion:
Every joke data is still in their source path (i.e. inside jokes) and ONLY their id is copied into newly created data path (userJokeLike and userJokeFavorite)
When you want to search for joke that user with id randomUserId likes, you should check for userJokeLike\randomUserId. Then from every joke id you got there, get the real data from inside source jokes path.
When you want to search for joke that is favorited by user with id randomUserId, basically, do the same as above.
When you want to count likes and favorite of each joke, just use something like this:
FirebaseDatabase.getInstance().getReference("userJokeLike")
.orderByChild().equalsTo("randomJokeId")
.addListenerForSingleValueEvent(new ValueEventListener() {
... onDataChange(DataSnapshot dataSnapshot) {
int jokeCount = dataSnapshot.getChildrenCount();
}
});
And there you go, hope this helps.
Note: I haven't check the last code, hope that work :p
EDIT:
Looks like I did misunderstand :D
The solution above is what I think is best for the sake of structure itself. But if we need something simple and fast, it is different for each case/situation. I think that the best solution if you want to get jokes with likes and favorites included (no need to create another request) then your structure should look like this:
jokes: {
randomJokeId: {
// joke data here
likes:{
randomUserId:true,
anotherUserId:true
},
favorites:{
randomUserId:true
}
}
}
It includes likes and favorite when you request jokes data. SO in each data you only need to check if current user's UID is exist inside likes and/or favorite. And the counter will be a lot easier this way.
Happy coding :)
Related
I want to delete the yellow user in the screenshot if he decides to delete his account. The blue X is a different user. How do I do that?
In the second picture is my attempt. I don't know how to get the userid of the blue X.
Your current data structure makes it easy to find the yellow Followers for a given blue Follow node. It does not however make it easy to find the blue node for a given yellow one. In fact, to allow that you will have to read all blue nodes, and check each individual Followers child node in turn.
To more easily allow your use-case, you'll want to also store the inverse data structure that allows you to find the blue Follow nodes for a given yellow Follower value. I typically refer to this as the Followee map, although I admit I'm not sure if that's even a word:
Followees: {
"ky....Yhi1": {
"L5w...6rF3": true
}
}
Now with this structure, you can find the "L5w...6rF3" key based on knowing the "ky....Yhi1" value and delete the user from the Followers node there.
We covered this scenario a few times before, so I recommend also checking out:
Firebase query if child of child contains a value
Firebase Query Double Nested
Many to Many relationship in Firebase
I try to make an app on Android for services reviews, every review is save like an element in the document "user" like this-
Everytime the user save a report I have see if inside the reports the field "plate" is existing comparing with the new one, I try query using the examples in the page arrays in Firebase
In the code i tried get with "whereEqualTo" method search by "reports.plate" or with the method "whereArrayContains" with the same field (the filter uid exits but in the first image doesn't show) any idea how i can search the document when some of the custom elements fields is equal
maybe sorry in advance for the english i'm practicing
Thanks in advance
I need to have one problem sorted out. I want a cloud function, where I need to loop through every Posts that has uniqueID and I want to sort those uniqueID's according to the value of TotalReactions. To me more vivid, suppose, the first post has totalReactions = 5, and second one has totalReactions = 6, then I need to have another RealTimeDatabase "PostArranged" which sorts them in descending order, so second post which has Total Reaction would be in first and then follows the one which has lesser TotalReaction...
Here is how my firebase realtime database looks like:
Posts
-L29TD-nsUYRu3wYcCQl
Caption: "First Screenshot"
CurrentUserReaction: "notreacted"
Image: "https://firebasestorage.googleapis.com/v0/b/nep..."
ReactingUser
<user-id>:"1"
<user-id>:"2"
Time: "13:40:54"
TotalReactions: "2"
Unique: "-L29TD-nsUYRu3wYcCQl"
UserPhoto: "https://firebasestorage.googleapis.com/v0/b/nep..."
Username: "Me"
Any help would be appreciated ..
This is not a good way to do what you want to do. In this method the database has to be sorted to another "ArrangedDatabase" every time a reaction is added which will happen in a high frequency. So it will be very expensive to do this with Cloud Functions.
Instead use orderByChild(), orderByKey(), orderByValue() to sort data when you're querying data.
Sorting data - Firebase documentation this show it quite well.
For anyone who want to do this in your RecyclerViewAdapter provided by Firebase, it is easily done... When you pass in those 4 parameters. Do not pass the database Reference, instead, make a new query, and make sure to sort that thing either by OrderByChild(), OrderByValue() or anything you want to order by... i.e.
In my case, I will do something like this:
q = mDatabaseReference.orderByChild("TotalReactions");
and pass q as parameter inside FirebaseAdapter, like this:
FirebaseRecyclerAdapter<Posts,PostViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Posts, PostViewHolder>(
Posts.class, R.layout.each_post_layout , PostViewHolder.class, q
) {
.
}
I am working on an Android application where there are two types of user. I differentiate them into the system by using the field UserType. I have a requirement where I have to copy data from one child node into another. I am using Firebase for my backend. I have gone through other answers but this requirement is unique in a way that, I want to copy data only on a particular node. Attaching the Firebase database structure
In this structure, if you can see I have expanded 2 child nodes of "users". One of the child has userType as Standard User and other child has userType as Guardian User.
1) I want to copy the "fullNameGuardian" child alone from the user with key starting with "L4bTr6q" to the user with key starting with "dC9Mq"
2) I want to copy the "standardEmail" child alone from the user with key starting with "dC9Mq" to user with key starting with "L4bTr6q".
And everytime I add a new user, the user can be with one of the userType "Standard User" or "Guardian User". So is there a possibility like I do it for every new user?
I am having difficulties figuring out how to do this. Any help is appreciated. Thanks a lot in advance.
I think you could save the other structure when you save the first one. For instance,
Save - node1/child
Update - node2/child
//and so on
Another way is using Firebase functions(Real database triggers) in order to automatically do something after something else had happened. Check it out.
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.