Read data from Firebase database when I have multiple unique ids - java

I'm having trouble writing in my database because I have multiple unique ids that I don't know how to access.
I know that for writing I need to use something like this:
DatabaseReference ref=database.getReference().child("Children")
ChildData data = new ChildData(fullName,age);
ref.push().setValue(data);
My database looks like this:
{
"Children" : {
"55hxObZjRLY9PSZxZxGgSTRKzpc2" : {
"-MzUih5e40OsWPF_Dj0q" : {
"age" : "22",
"fullName" : "Cristina "
},
"plays" : {
"-MznnNih5fItYf2usXB4" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
}
},
"Data" : {
"id1" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
}
I need the "plays" child to be under "fullName" in "-MzUih5e40OsWPF_Dj0q", not as a separated child. How can I access the path without hardcoding it like this ref.child("MzUih5e40OsWPF_Dj0q").child("plays").push().setValue(data)? I will have multiple children in "Children" with different ids, I won't be able to harcode them.
Is there any function that returns the path for the unique id?
Here is the entire function:
public void writeNewData
(String fullName,String age) {
DatabaseReference reference = database.getReference().child("Data");
DatabaseReference ref=myRef.push();
ChildData data = new ChildData(fullName,age);
ref.push().setValue(data);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
DatabaseReference playRef=ref.child("plays");
DatabaseData databaseData = ds.getValue(DatabaseData.class);
playRef.push().setValue(databaseData);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
Edit: This is my desired schema:
{
"Children" : {
"55hxObZjRLY9PSZxZxGgSTRKzpc2" : {
"-MzUih5e40OsWPF_Dj0q" : {
"age" : "22",
"fullName" : "Cristina ",
"plays" : {
"-MznnNih5fItYf2usXB4" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
},
}
},
"Data" : {
"id1" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
}

If you want the plays information to be a sibling of the age and fullName properties, then you will need to have a plays field/property in your ChildData class.
You'll need two classes, one to represent a "play" and one to represent a "child". At its minimum these will look like:
public class Play {
public String centiseconds, currentDate, currentHour, numberOfFails, seconds;
}
public class Child {
public String age, fullName;
public Map<String, Play> plays = new HashMap<>();
}
If you read/write this class, you will get plays nested under the child's data.

Related

Trying to retrieve data from firebase where the category is equal to the string

I am trying to retrieve data from the Firebase Realtime Database and I only want where the category is equal to a String. For example, if my string is football then I should get all the data that has the category football in it. I run my app with the code I am about to show you but I get nothing but a blank page. I don't know what I am doing wrong.
databaseReference = FirebaseDatabase.getInstance().getReference();
if (Categories.InternetConnection.checkConnection(Categories.this)) {
databaseReference.child("Sports").orderByChild("category").equalTo("football")).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myUploads.clear();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
for (DataSnapshot postsnapshot : userSnapshot.getChildren()) {
Model_Information upload = postsnapshot.getValue(Model_Information.class);
Collections.shuffle(myUploads);
myUploads.add(upload);
recyclerView.invalidate();
}
}
linearLayoutWithoutItems.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
aAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(Categories.this, databaseError.getMessage(), Toast.LENGTH_LONG).show();
}
});
Firebase Json
{
"MyStudents" : {
"KihlyfLkJMQ5uZWBDgLWNuBHKAE2" : {
"-MSr8HG6QCR2sO8MZHoM" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Benny",
"time" : "2:47 AM",
"timestamp" : 1613684875762
},
"-MSr8awtvzrmm3P6A2LB" : {
"category" : "Basketball",
"created" : "2-19-2021",
"name" : "patrick",
"time" : "2:49 AM",
"timestamp" : 1613684960454,
},
"-MSr8mSn5OSTu5vdT4Wt" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Shawn",
"time" : "2:50 AM",
"timestamp" : 1613685007616,
}
{
"MyStudents" : {
"WahlyfLkJMQ5uZWBDgLWNuBHKAE2" : {
"-MSr8HG6QCR2sO8MZHoM" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Len",
"time" : "2:47 AM",
"timestamp" : 1613684875762
},
"JJr8awtvzrmm3P6A2LB" : {
"category" : "Basketball",
"created" : "2-19-2021",
"name" : "Armstrong",
"time" : "2:49 AM",
"timestamp" : 1613684960454,
},
"-JJr8mSn5OSTu5vdT4Wt" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Bill",
"time" : "2:50 AM",
"timestamp" : 1613685007616,
}
The problem in your code lies in the fact that you are using an incorrect query:
databaseReference.child("Sports").orderByChild("category").equalTo("football"))
Assuming that MyStudents is a child right under your root node and the following statement:
if (Categories.InternetConnection.checkConnection(Categories.this)) { /* ... */ }
Returns true, please use the following query:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child(uid);
Query queryByCategory = uidRef.orderByChild("category").equalTo("Football");
queryByCategory.addValueEventListener(/* ... */);
Things to notice:
KihlyfLkJMQ5uZWBDgLWNuBHKAE2 is the UID of the logged-in user and should be added as a child in the reference.
The value of the category property is called "Football" and not "football", with lower-case "f".
Edit:
According to your last comment:
I'm not trying to just get their information I'm trying to get everyone that has students whose category is Football
There is no way you can achieve that using your actual database structure. The most simple solution I can think of is to create a new node that contains all Model_Information objects, no matter the user is. This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Database.
Also, when you are duplicating data, there is one thing that needs to keep in mind. In the same way, you are adding data, you need to maintain it. In other words, if you want to update/delete an item, you need to do it in every place that it exists.
Here is the answer. Hopefully its helpful for someone :)
databaseReference = FirebaseDatabase.getInstance().getReference().child("MyStudents");
if (Categories.InternetConnection.checkConnection(Categories.this)) {
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myUploads.clear();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
for (DataSnapshot postsnapshot : userSnapshot.getChildren()) {
Model_Information upload = postsnapshot.getValue(Model_Information.class);
Collections.shuffle(myUploads);
if (upload.getCategory().equals("Football")) {
myUploads.add(upload);
}else{
Toast.makeText(Categories.this, "No results", Toast.LENGTH_LONG).show();
}
recyclerView.invalidate();
}
myUploads.add(upload);
recyclerView.invalidate();
}
}
aAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(Categories.this, databaseError.getMessage(), Toast.LENGTH_LONG).show();
}
});

Get uid in list by searching child values firebase android

{
"Mp6FLLdcSeXpfGPwP5i0ZBNZxd63" : {
"Age" : "20",
"Full name" : "Mike",
"Intent" : "Both",
"Reward" : "Nothing ",
"Variablex" : "one name",
"imageuri" : "images/Mp6FLLdcSeXpfGPwP5i0ZBNZxd63.jpeg"
},
"fWJcCPF16dUMKn1Sxz01VjF9Kgq2" : {
"Age" : "19",
"Full name" : "Other guy",
"Intent" : "Looking for help",
"Reward" : "nothing ",
"Variablex" : "one name",
"imageuri" : "images/fWJcCPF16dUMKn1Sxz01VjF9Kgq2"
}
}
This is my database. I want to get all the users with the same variablex. But i want only the id, the parent node. I want basically to build an array that contains all the ids of the users whose child value variablex is the same. And then use this array to call one user at a time get the id, perform other tasks with it etc.
public void othershit() {
Query qname3 = mDatabase.child("Variablex").orderByChild("Variablex").equalTo(userinput);
qname3.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
GenericTypeIndicator<List<String>> t = new GenericTypeIndicator<>();
List users = dataSnapshot.getValue(t);
textView8.setText(users.get(0).toString());
}
This is trigered with a button but everytime it crashes. Also i have three users with the same variablex. The structure is the same, this is a bit outdated version of my database but it is essentially the same.
Try using
dataSnapshot.getKey();
To retrieve the parent key of the found node which in your case is the FUID.
Edit -
Lets say your parent node for all the data is users
{
"users" :{
"Mp6FLLdcSeXpfGPwP5i0ZBNZxd63" : {
"Age" : "20",
"Full name" : "Mike",
"Intent" : "Both",
"Reward" : "Nothing ",
"Variablex" : "one name",
"imageuri" : "images/Mp6FLLdcSeXpfGPwP5i0ZBNZxd63.jpeg"
},
"fWJcCPF16dUMKn1Sxz01VjF9Kgq2" : {
"Age" : "19",
"Full name" : "Other guy",
"Intent" : "Looking for help",
"Reward" : "nothing ",
"Variablex" : "one name",
"imageuri" : "images/fWJcCPF16dUMKn1Sxz01VjF9Kgq2"
}
}
}
So here is what you need to do to get the list of all the ids which match the required
List<String> userIds = new Arraylist<>();
Query qname3 = mDatabase.child("users").child("Variablex").orderByChild("Variablex").equalTo(userinput)..addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userIds.add(dataSnapshot.getKey());
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});

Check if user exists in Firebase database across multiple children nodes

I've a database like this
"Node" : {
"Location_1" : {
"ID1" : {
"address" : "address1",
"balance" : "20",
"batch" : "xyz",
.
.
.
"studentID" : "ID1",
"studentName" : "Username",
"total" : "amount"
}
},
"Location_2" : {
"ID2" : {
"address" : "address2",
"balance" : "0",
"batch" : "xyz",
.
.
"studentID" : "ID2",
"studentName" : "username",
"total" : "amount"
}
}
"Location_3" : {
"ID3" : {
"address" : "address3",
"balance" : "0",
"batch" : "xyz",
.
.
"studentID" : "ID3",
"studentName" : "username",
"total" : "amount"
}
}
I'm able to check if the ID1 exists in a particular Location_1 using the code given below, but I'm unable to find if the ID1 exists across different Location_X id's.
String url = "https://firebaseURL/Node/";
url = url + Location_1;
databaseReference = FirebaseDatabase.getInstance().getReferenceFromUrl(url);
databaseReference.child(ID1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
Toast.makeText(getApplicationContext(), "ID already present. Enter unique ID!", Toast.LENGTH_SHORT).show();
}
else { // not present, so go ahead and add
}
I tried using a function like this to check if the user is present in all the subNodes.
private boolean checkIfUserExists(String ID) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("Location_1");
.
.
String url = "https://firebaseURL/Node/";
databaseReference = FirebaseDatabase.getInstance().getReferenceFromUrl(url);
for(String s: arrayList){
if(getUserExists())
break;
databaseReference.child(s).child(ID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
setUserExists(true);
}
}
But always the function getUserExists return false. So I end up adding a new user in different location or updating the user's info in the same location.
Please let me know how to proceed on checking the existence of the userID in all the locationIDs

how to fetch multiple data simultaneously from firebase database

Fetch messages method
private void fetchMessages() {
rootRef.child("Messages").child(MessageSenderId).child(MessageRecieverId)
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Messages messages = dataSnapshot.getValue(Messages.class);
messagesList.add(messages);
messageAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
Defining Ids
MessageSenderId = mAuth.getCurrentUser().getPhoneNumber();
MessageRecieverId = getIntent().getStringExtra("visit_user_id");
trying to make a basic chat app
Since only the senders id is called in rootref only the messages i send r being displayed in d recyclerview... im unable to receive messages because of this... how can i make it to retrieve recievers id and senders id also at the same time
Database strucutre
{
"Messages" : {
"+918105571584" : {
"+919945342730" : {
"-L58IPCLEeE21vH_-1Ry" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427022478,
"type" : "text"
},
"-L58IU1VIHN0rHaUox3a" : {
"message" : "Hello",
"seen" : false,
"time" : 1518427042257,
"type" : "text"
},
"-L58IYN1GpHPdkWCY7Hn" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427060021,
"type" : "text"
}
}
},
"+919945342730" : {
"+918105571584" : {
"-L58IPCLEeE21vH_-1Ry" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427022478,
"type" : "text"
},
"-L58IU1VIHN0rHaUox3a" : {
"message" : "Hello",
"seen" : false,
"time" : 1518427042257,
"type" : "text"
},
"-L58IYN1GpHPdkWCY7Hn" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427060021,
"type" : "text"
}
}
}
},
"Users" : {
"+918105571584" : {
"Email" : "",
"Name" : "Akash",
"Quote" : "",
"Status" : ""
},
"+919945342730" : {
"Email" : "",
"Name" : "Sav",
"Quote" : "",
"Status" : ""
}
}
}
According to your last comment, I understand that you can display only the messages that correpond to a single user. A user can see only his messages butd not other user messages. To solve this, you need to create chat rooms, in which every user can add messages that can be seen by all chat room members.
So for that, you need to change your database structure. You cannot achieve this, using the actual database.

How to get sorted data from Firebase Database?

How I can get TOP three users(maybe in HashMap) with name and userScore from all users in Firebase Database? HashMap must be order by userScore. Or get ArrayList<User> usersList with three sorted users by userScore.
database
{"top_clicker_db" : {
"total_clicks" : 3401,
"user" : {
"-KkePRVzO_lLLgp7fqX0" : {
"name" : "fly",
"userScore" : 2000
},
"-KkjWk0L2lR8RwUXF2Bd" : {
"name" : "lg",
"userScore" : 24
},
"-KkjjxNw8fj_XG9uUPEg" : {
"name" : "fjfg",
"userScore" : 304
},
"-KkjoakdLIjYlBEM1pkq" : {
"name" : "Geny",
"userScore" : 100
},
"-KklVAOkk2WJaRmH9cKk" : {
"name" : "fly",
"userScore" : 941
}
}
}
}
I need:
fly=2000;
fly=941;
fjfg=304;
To solve the problem in easiest way possible i recomand you change you database structure like this:
{"top_clicker_db" : {
"total_clicks" : 3401,
"user" : {
"-KkePRVzO_lLLgp7fqX0" : {
"fly" : 2000
},
"-KkjWk0L2lR8RwUXF2Bd" : {
"lg" : 24
},
"-KkjjxNw8fj_XG9uUPEg" : {
"fjfg" : 304
},
"-KkjoakdLIjYlBEM1pkq" : {
"Geny" : 100
},
"-KklVAOkk2WJaRmH9cKk" : {
"fly" : 941
}
}
}
}
You need a single child with the user name as the key and the score as the value. The benefits of this structure is that you need to query just once. To achieve this, please use the following code:
DatabaseReference yourRef = FirebaseDatabase.getInstance().getReference().child("top_clicker_db").child("user").child(userId);
Query query = yourRef.child(userName).orderByValue().limitToFirst(3);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("TAG", dataSnapshot.getKey() + "=" + dataSnapshot.getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
query.addListenerForSingleValueEvent(eventListener);
Hope it helps.
You said you cannot change your database structure in the comment in #alex-mamo 's answer, but how about adding a new node?
If you can, denormalize your data may also be a good solution.
https://firebase.google.com/docs/database/web/structure-data
"total_clicks" : 3401,
"user" : {
"-KkePRVzO_lLLgp7fqX0" : {
"name" : "fly",
"userScore" : 2000
},
"-KkjWk0L2lR8RwUXF2Bd" : {
"name" : "lg",
"userScore" : 24
...
},
"scores" : {
"-KkePRVzO_lLLgp7fqX0" : {
"fly" : 2000
},
"-KkjWk0L2lR8RwUXF2Bd" : {
"lg" : 24
},
...
}
I solved the problem. But now I think how I can limited my list only for 3 users.
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
getTopThreeUsers((Map<String, Object>) dataSnapshot.getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
private void getTopThreeUsers(Map<String, Object> users) {
HashMap<String, Long> namesAndScores = new HashMap<>();
for (Map.Entry<String, Object> entry : users.entrySet()) {
Map singleUser = (Map) entry.getValue();
namesAndScores.put((String) singleUser.get("name"), (Long) singleUser.get("userScore"));
}
Set<Map.Entry<String, Long>> set = namesAndScores.entrySet();
List<Map.Entry<String, Long>> list = new ArrayList<>(set);
Collections.sort(list, new Comparator<Map.Entry<String, Long>>() {
public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) {
return (o2.getValue()).compareTo(o1.getValue());
}
});
topName1.setText(list.get(0).getKey());
topName2.setText(list.get(1).getKey());
topName3.setText(list.get(2).getKey());
topScore1.setText(String.valueOf(list.get(0).getValue()));
topScore2.setText(String.valueOf(list.get(1).getValue()));
topScore3.setText(String.valueOf(list.get(2).getValue()));
}

Categories