Firebase Database costum push method or reverse data tree? - java

I'm using push() method to create unique ids for database but when I create an id with push method its added to bottom of tree but I want it to be on top. How can I do that?
For example in this picture bottom one is newest one I want it to be on top. How can I do that?
Picture
I want this because I use RecyclerView with Firebase adapter and adapter start to read from top.
edit: how to get data from bottom to top from firebase?
This question is what I want but there is no useful answer.

I'm using push() method to create unique ids for database but When i create an id with push method its added to bottom of tree but i want it to be on top
When you are using the push() method, the objects in the Firebase Console are ordered chronologically and unfortunately there is nothing you can do about it. This order cannot be changed. If you want to display the items from the datababse in a RecyclerView and hypothetically speaking, you would have been able to change the order in the console, it doesn't mean that this order is the same with order in the RecyclerView. To display your items in a particular order, I recommend you to use a Query and sort them according to a timestamp property. For that, please see Frank van Puffelen's answer from this post and if you are using the Firebase-UI library, please see my answer from this post.

you can write a simple query to get data as you need it
add date parameter to your object then query the data by the date
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.child("data").orderByChild("date");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
// fill recyclarView with data
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Related

Could I use if (snapShot.hasChild(uid) in firebaseRecycleOptions? I am using Firebase Recycle adapter to retrieve data under node: "Groups"

private void RetrieveAndDisplayGroups() {
FirebaseRecyclerOptions<GroupModel> options = new FirebaseRecyclerOptions.Builder<GroupModel>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("Groups"), new SnapshotParser<GroupModel>() {
#NonNull
public GroupModel parseSnapshot(#NonNull DataSnapshot snapshot) {
// I tried to use if statment before return.
return new GroupModel(snapshot.child("groupName").getValue().toString(), snapshot.child("groupDescription").getValue().toString());
}
}).build();
modelAdapter = new GroupModelAdapter(options, getContext());
recyclerExploreGroupView.setAdapter(modelAdapter);
}
So I am making a group chat app.
In my app, I want to show the users only the groups they have created.
In the database, under node "Groups", I have all the groups created by all users.
I am using firebase recycle adapter to retrieve data from firebase real time database.
I am not familiar with how FirebaseRecycleOptions work. I think it returns a set of the model object I passed.
I try to use if statement before new firebaseRecycleOptions return. But I got red line.
The goal is to check if each group has a child as a requirement. And only retrieve the ones who have it.
Any help would be appreciated.
If you want to only show a subset of the child nodes in the adapter, you should use a query to retrieve only those child nodes from the database.
It's hard to be certain without seeing your database, but using this query in the adapter might be an option:
FirebaseDatabase.getInstance().getReference()
.child("Groups")
.orderByChild("groupName")
.startAt(null)
Since null is the first value in Firebase Realtime Database ordering, this will return any node that has a groupName value.

How to show the new entry on the top list RecyclerView [duplicate]

I am developing an Android chat application in which I need to order the conversation details by the date. My firebase data structure is mentioned below.
Now I want to retrieve and show the data on the latest date on my RecyclerView from Firebase Realtime Database based on timestamp.
I have tried the following approaches.
final DatabaseReference nm =
FirebaseDatabase.getInstance().getReference("Transaction");
Query query = nm.orderByChild("Date").limitToFirst(5);
;
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
listData.clear();
if (dataSnapshot.exists()) {
for (DataSnapshot npsnapshot : dataSnapshot.getChildren()) {
Transaction ld = npsnapshot.getValue(Transaction.class);
listData.add(ld);
}
Tadapter = new TransactionAdapter(listData);
rv.setAdapter(Tadapter);
Log.d(TAG, "Total Count" + Tadapter.getItemCount());
}
}
}
I am developing an android chat application in which I need to order the conversation details by the date.
As I see in your screenshot, your Date property is of type String. This means that you cannot call:
.orderByChild("Date")
And expect to behave as it was a Timestamp. When you order String elements, the order that you get is always lexicographically. This means that Strings doesn't consider any sort of numeric values when sorting, especially when it comes to the dates, even if the dates contain numbers, as your first element does:
Date: "30/7/2021"
So using String values when querying your database it's not an option. However, I see you already have a Timestamp property. Maybe on that property, it was supposed to do the ordering. If that was not the case, I suggest you change the type of the Date property from String to Timestamp, as explained in my answer from the following post:
How to save the current date/time when I add new value to Firebase Realtime Database
Now I want to retrieve and show the data on the latest date on my RecyclerView
This means that most likely you need to reverse the order, meaning that all your transactions have to be displayed in your RecyclerView descending. In this case, there are a few options that you have, either on the server or on the client.
Assuming that you have changed the type of your Date property from String to Timestamp, then you can simply consider storing an inverted Timestamp value like this:
Firebase-root
|
--- transactions
|
--- 1
|
--- Date: 1627714194
|
--- invertedDate: -1627714194
See, the invertedDate property holds a negative value. Since by default, the elements are ordered ascending, to be able to order the transaction desecendiong, you should simply use:
Query query = nm.orderByChild("invertedDate").limitToFirst(5);
On the other hand, there are some workarounds that can be made to achieve the same thing on the client, as explained in my answer from the following post:
How to arrange firebase database data in ascending or descending order?
Query query = nm.orderByChild("Date").limitToFirst(5);
Firebase realtime database sorts in ascending order that means those 5 nodes that you'll receive will be the oldest.
I want to retrieve and show the data in latest date
Try using limitToLast instead which will return the last 5 documents after ordering the nodes by Date field i.e. the 5 latest nodes.
Query query = nm.orderByChild("Date").limitToLast(5);
You can read more about that at sorting and filtering data.

Searching a firebase database

Preface:
For this question to make sense, I need to describe my intent for the database. It will be used to store user data based on a grid of latitude and longitude sectors created by finding the floor value of the exact coordinates of the user when they sign up or log in. The reduced coordinate values are then concatenated, saved in shared preferences on the user's phone, and then set as the primary nodes in the database. This allows searching through the database to be restricted to just the sector the user is currently in which is required by a feature of the app. See the example the nodal layout of the database below:
The Problem:
This system works great, except for that when the user logs in on a new device (or if the shared preferences are lost) from outside the original sector, or from the previous sector, there is no way to know the previous or original sector value.
The Answer:
The answer I came up with is to search every single sector node in the database for the unique uid easily acquired by the following code:
FirebaseAuth mAuth = FirebaseAuth.getInstance()
String currentUser = mAuth.getCurrentUser().getUid();
However, I don't know how to search through every single node (of which there may be thousands because there are thousands of potential sectors) in the database for a particular child. Note that every primary node has a different name, but they all contain the child "users" which can then hold any number of child "uids."
Once the current uid is found in the previous sector-node, my intent is to transfer all of the children of the current uid in the previous sector to the new one. I want to avoid iterating locally through the entire database for the uid as well.
private DatabaseReference userRef = FirebaseDatabase.getInstance().getReference();
mLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String email = mEmail.getText().toString();
final String password = mPassword.getText().toString();
final String currentUserId = mAuth.getUid();
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(LoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
Toast.makeText(LoginActivity.this, "sign in error", Toast.LENGTH_SHORT);
} else {
if (task.isSuccessful()){
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
})
}
}
}
});
}
});
All this needs to occur after the success of a sign-in event as shown above. I have a feeling I need to use a dataSnapshot for this but I am unsure. I also read another post and considered the following to be the start of something that might work, but I don't know:
Query searchQuery = userRef.child("Users").equalTo(currentUserId);
The flow of the query should be this: Search first node -> Navigate to Users --> iterate through for currentUid --> If currentUid is not found Search the second node... and so on and so forth until the currentUid is found.
If anyone has the answer or any suggestions, guidance, or hints, I would be very grateful. Thank you.
A Firebase Database query can only contain one unknown level in the path. Your current structure doesn't allow you to search all sectors for a specific user. You can search across all users in a single section, but not across sectors.
So while your current code makes it easy to find all users in a specific sector, or even range of sectors, it doesn't make it easy to find the sector for a specific user. To allow the latter use-case you'll need to add an additional data structure for that purpose. Typically something like:
"user-locations": {
"$uid": "
"sector": "37-123",
"location": "..."
}
}
So this means that when a user moves, you'll need to update their location in two places.
This sort of data duplication is common in NoSQL databases, where you need to update your data model to allow the use-cases. It is also quite common to have more complex write operations, in order to make read operations simpler and more scalable.
For more on this, see my answers to:
Firebase Query Double Nested
Firebase query if child of child contains a value
And:
NoSQL data modeling
Firebase for SQL developers

How to show items from two children in one RecyclerView from Firebase

Below is image representation of my firebase where user upload items under Electronics or Books category and also more categories. I want to build an activity with RecyclerView where I want to show the only item uploaded by a user. Since I'm using userid which is unique to push the details of the item inside a child, I can use userid to retrieve the items from child and display in firebase. But, how to search in each child from different category and show it in one RecyclerView.
My Code to Show the items from Electronics child is
dbreference = FirebaseDatabase.getInstance().getReference("Electronic").child("userid");
dbreference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()) {
for (DataSnapshot data : snapshot.getChildren()) {
final Solditem b1 = data.getValue(SoldItem.class);
child_count++;
list.add(b1);
staggeredBooksAdapter.notifyDataSetChanged();
}
}
}
But I also would like to show the uploaded item by a user which equals to userid as key from Books in the same RecyclerView.
To delete an item from any category I use
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Query sellerquery = ref.child("Electronic").child("userid");
sellerquery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot appleSnapshot: dataSnapshot.getChildren()) {
appleSnapshot.getRef().removeValue();
}
}
}
To delete all the records of a user-uploaded item which key-value equals to userid, I need to repeat above code.
Is there any best and short method to delete all the records from any category which key-value equals to userid.
Thanks in advance.
While structuring your data in Firebase, you really need to think about the structure of your data very carefully so that you can run efficient queries on them. For example, in your case, you should have structured your data as follows.
userid
- Electronics
- Camera
- Cooker
- Books
- A brief history of time
- Inferno
Hence you could run your queries in such a way that, you could have all the items under a certain userid at once.
If you really need the structure that you have now for other sets of queries that you are planning to do in your application, think about replicating your data as well. That is, you might consider having duplicate entries of your data (replication) in different structure so that you can perform efficient queries. For example, the current structure of your data is suitable for the following query.
Get all userid under a specific category.
I think you have got my point. If you do not want to change the structure of your data then I am afraid that you might have to get all the data in your application from firebase first. Then you have to loop through the data yourself to find the elements that you actually needed.
Hope that helps!

Java: Sort child based on data in Firebase Database

Image here. Data does not sort accordingly like I wanted (O+, O+, A)
Currently, I have data that stored exactly like in the picture above, I want to make all the blood groups to be placed accordingly. For example, It will have only 0+ until the lists end. It will continue with different blood groups such A+, A- etc.
Can firebase actually sort that data? I was looking around, but could not find anything
Inside the Firebase Console, all the nodes are sorted lexicographically by key and this can't be changed.
However, when you retrieve the data on the client, you can choose to sort by one of the child properties. This way they will be sorted by the time they are shown to the client. For example:
// the reference to where your people are stored
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
// create the query
Query peopleBloodTypeQuery = mDatabase.child("people").orderByChild("bloodgroup");
// query the people
peopleBloodTypeQuery.addChildEventListener(new ChildEventListener() {
// add a child added listener
#Override public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
// do whatever here - I just print the key of each added child
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
}
});

Categories