I am working on app where I want to show the data only of the users whose contact numbers are saved in the phone. So, I retrieved a list of contact numbers contactList. Now, I want to get all the contactList user's post from Firebase. Is there any way I can ask the Firebase for only those nodes in my contactList. One Way is to retrieve all users and then get relevant users from that (like I did below). Is there any better way to do so ?
Users: {
7828272892 : {
name: xyz,
gender: male,
phoneNo: 7828272892
Posts: {
SomeKey1: {
content: "This is post 1", Var2: "kkk"} }},
7924272894 : {name: abc, gender: male, phoneNo: 7924272894}
}
Code:
databaseReference.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
List<Post> allItems = new ArrayList<Post>();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
if (contactList.contains(postSnapshot.child("phoneNo").getValue())) {
// retrieve posts
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Is there any way I can ask the firebase for only those nodes in my contactList?
Yes, the way in which you already do this.
Is there any better way to do so?
The way in which you do this is a common practice used in Firebase. You query the database and check is the data already exists in the list, in your case in the contactList. If the list contains that phoneNo then you can retrieve the posts.
Try this code to read multiple nodes data..
mFirebaseInstance = FirebaseDatabase.getInstance();
mDatabase = mFirebaseInstance.getReference("usersDb/UserTable");
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUserList.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
User user = dataSnapshot1.getValue(User.class);
mUserList.add(user); // add all data into list.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Related
I created a social media app. Suppose I have one array list which contains all the uids of users I follow on my app, stored in child of (following), I also created a child of (posts) which has all posts, posted by all users. The problem is I don't want to use snapshot.getChildern() to retrieve posts which equals following because it downloads whole data under 'posts' child. Is there any way I can retrieve only those posts which matches with 'following' array list?(for Posts Database looks like this)-->
Clicks / UID {title : "sky" imageurl : "https...." publisher : "UID" timestamp : "1666456456.."}
and second one --> follow / UID / following / other user's uid : true
functions I use :
private void checkFollowing(){
followingList = new ArrayList<>();
DatabaseReference reference = Util.getDatabase().getReference("follow")
.child(Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getUid())
.child("following");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
followingList.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
followingList.add(dataSnapshot.getKey());
}
readClicksPosts();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void readClicksPosts() {
DatabaseReference reference = Util.getDatabase().getReference("Clicks");
reference.orderByChild("timestamp").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
clicks_models_List.clear();
for (DataSnapshot datasnapshot : snapshot.getChildren()) {
Clicks_Model clicks_model = datasnapshot.getValue(Clicks_Model.class);
for (String id : followingList) {
assert clicks_model != null;
if (clicks_model.getPublisher().equals(id)) {
clicks_models_List.add(clicks_model);
}
}
}
Collections.reverse(clicks_models_List);
clicksAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
DatabaseReference.goOffline();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
I just want to show posts from people I follow, what should I do if I don't to use .getChildren() method. Please keep in mind the posts are going to update frequently.
I need to get the specific user data using the user email on the real time database. This is my code, This code running without errors but the data is not display in the interface.I think datasnapshot retrieving part is not correct. please help me to solve this.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String userEmail = user.getEmail();
DatabaseReference rootReference = FirebaseDatabase.getInstance().getReference();
Query myUsersQuery = rootReference.child("Children").orderByChild("childrenParentEmail").equalTo(userEmail);
myUsersQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("Children").getValue(String.class);
childrenNameEdt.setText(name);
childrenBirthdayEdt.setText(dataSnapshot.child("childrenBirthday").getValue(String.class));
childrenParentNameEdt.setText(dataSnapshot.child("childrenParentName").getValue(String.class));
childrenParentAddressEdt.setText(dataSnapshot.child("childrenParentAddress").getValue(String.class));
childrenParentContactNumberEdt.setText(dataSnapshot.child("childrenParentContactNumber").getValue(String.class));
childrenParentEmailEdt.setText(dataSnapshot.child("childrenParentEmail").getValue(String.class));
childrenTransportTypeEdt.setText(dataSnapshot.child("childrenTransportType").getValue(String.class));
childrenTransportContactNumberEdt.setText(dataSnapshot.child("childrenTransportContactNumber").getValue(String.class));
//childrenID.setText(dataSnapshot.child("password").getValue(String.class));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
When you execute a query against the Firebase Realtime Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
Your code will need to handle that list, by looping over dataSnapshot.getChildren(). So something like:
myUsersQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren();
String name = snapshot.child("Children").getValue(String.class);
childrenNameEdt.setText(name);
...
I want to get data from firebase without changing my database structure because I have two condition:
When admin logins then he can see all employees data for the selected year or say year-wise.
But when employees login then they should be able to see their individual data from all the years using employee code, which is a child also (blue tick in the picture).
Below is my database structure:
The child marked in red is unknown in case of employee's access and the blue tick denotes an employee who may be present in every year.
All I want is to achieve the 2nd condition. But I am unable to get the data.
Here is my code:
private void retrieveData() {
final String shift = kvName.getText().toString();
final String employeeCode = empCode.getText().toString();
dbRef.child("Apar").child(shift);
dbRef.orderByChild(employeeCode).equalTo(employeeCode).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot datas1 : dataSnapshot.getChildren()) {
for (DataSnapshot datas2 : datas1.getChildren()) {
// String aparGrading= datas2.getKey(); //unable to figure out how to get
// Toast.makeText(Apar.this, aparGrading, Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Your current data structure makes it easy to find the information for all employees for a specific year. It does however not make it easy to find the information for a specific employee across all years.
To do the latter, you have two options:
Check each year for the presence of a node for that employee ID.
Add an additional data structure that maps from each employee ID to the years for which they have data, and then load each year's data for that employee individually
For more on this, also see:
Many to Many relationship in Firebase
Firebase query if child of child contains a value
Firebase Query Double Nested
Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly, to learn why the second approach is not as slow as you may think.
After reading the various answers on this topic linked above by Mr. #Frank van Puffelen and spending some times over it, the problem is finally solved now without changing my database structure.
Below is screenshot of the result which I wanted:
Here is my modified and working code :
private void retrieveData() {
final String shift = kvName.getText().toString();
final String employeeCode = empCode.getText().toString();
final DatabaseReference aparRef = dbRef.child("Apar").child(shift);
aparRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
list = new ArrayList<>();
if (dataSnapshot.exists()) {
for (DataSnapshot dataS1 : dataSnapshot.getChildren()) {
if (dataS1.hasChild(employeeCode)) {
AparData aparData = dataS1.child(employeeCode).getValue(AparData.class);
list.add(aparData);
rvAPAR.setHasFixedSize(true);
rvAPAR.setLayoutManager(new LinearLayoutManager(Apar.this));
rvAPAR.setItemAnimator(new DefaultItemAnimator());
aparAdapter = new AparAdapter(Apar.this, list);
rvAPAR.setAdapter(aparAdapter);
} else {
Toast.makeText(Apar.this, "No Data Found!!", Toast.LENGTH_SHORT).show();
}
}
} else {
Toast.makeText(Apar.this, "Not Data Found!!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
I have to fetch all children data from firebase real time database? I want to fetch received messages of User2. How to do that? Database example is as given below -
To be able to fetch the children data, try the following:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("users").child("User1").child("MSG_TYPE_SENT");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String msgContent=datas.child("msgContent").getValue().toString();
String msgType=datas.child("msgType").getValue().toString();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This will give you the msgContent and the msgType, to retrieve any data from the database, you need to pass through every node example:-
getReference("users").child("User1").child("MSG_TYPE_SENT");
Then you can loop inside the ids and retrieve the data.
Here you can fetch the User2 Messages Received
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("users");
mDatabase.child("User2").child("MSG_TYPE_RECEIVED").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot spanshot : dataSnapshot.getChildren()){
String content=snapshot.child("msgContent").getValue(String.class);
String type=snapshot.child("msgType").getValue(String.class);
//then you can log those values
Log.d("Values:",""+content+""+type);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
If the message received change at any time (lets say you want to implement the delete option in realtime of the message like whatsapp) .addValueEventListener will update your UI in realtime if you have coded to show that the message has been deleted
I currently have a users collection in my Firebase real-time database that contains all my users and a collection that contains the name of books and the ratings(number of thumbs up and down). I am trying to make a application that will display book titles constantly(or the ones that are in my db) so that people can rate them, however I need to be able to check if a user has already viewed this book title or not(this is the part i need help with). Can someone help me with pulling the data from Firebase and comparing it to see if the user has viewed this book title or not. This is what my db setup looks like
Also if someone has a better way of doing this please explain!!!
First, change books_viewed into an array. Read this for arrays in Firebase Realtime Database
Now that it's an array, you can get that as a ArrayList<String> in your app.
public class User {
public ArrayList<String> booksViewed;
... // Other variables
}
Then just use the contains function to check if the book you need to find is in that list
DatabaseReference userRef = FirebaseDatabase.getInstance().getReference().child("Users").child("<UserID>")
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
String bookTitleYouAreChecking = "Twilight"
if (user.booksViewed.contains(bookTitleYouAreChecking)) {
// User has viewed
} else {
// User has not viewed
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// ...
}
})
To solve this, please use the following method that checks if a user had viewed a book or not:
private void checkBookTitle(String bookTitle) {
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child("Users").child(uid).child("books_viewed");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue().equals(bookTitle)) {
Log.d(TAG, "User has viewed this book");
} else {
Log.d(TAG, "User has not viewed this book");
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
};
ref.addListenerForSingleValueEvent(valueEventListener);
}