I'm a little stuck, to create FirebaseRecyclerOptions that should present the results in recursive in database
I mean if I had in Data base (Crossfit - > APR_09_2021 -> 10_12 -> "some data collection")
So I noticed if I didn't pass the specific path to "some data collection" so it can't retrieve the data
I mean: DatabaseReference mbase = FirebaseDatabase.getInstance().getReference().child("Crossfit").child(APR_09_2021)
So my question how do I get all results from the database.
for all the dates that I have under the CrossFit
Thanks.
DatabaseReference mbase = FirebaseDatabase.getInstance().getReference().child("Crossfit");
recyclerView = findViewById(R.id.recycler_plan);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
FirebaseRecyclerOptions<TrainingTrainerCollector> options = new FirebaseRecyclerOptions.Builder<TrainingTrainerCollector>()
.setQuery(mbase, TrainingTrainerCollector.class).build();
recycleViewAdapter = new TrainerRecyclerviewViewAdapter(options,"Crossfit");
recyclerView.setAdapter(recycleViewAdapter);
recycleViewAdapter.startListening();
super.onStart();
https://i.stack.imgur.com/x4Fik.png
https://i.stack.imgur.com/1CW2U.png
You cannot do that with your actual database structure. When you are using the following reference:
DatabaseReference mbase = FirebaseDatabase.getInstance().getReference().child("Crossfit");
It means that you are trying to read all children under "Crossfit". So when using the Firebase-UI library, it means that you can only get children one level deep. According to your schema, your data is two-level deep, see?
APR_10_2021 -> 10_12 -> Data
There are two ways in which you can solve this. The first option you have is to create a new node called "allCrossfits" where you should add all "TrainingTrainerCollector" objects. This practice is called denormalization and is a common practice when it comes to Firebase. If you are new to NoSQL databases, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding.
So, your new reference should look like this:
DatabaseReference mbase = FirebaseDatabase.getInstance().getReference().child("allCrossfits");
This reference should be passed to the "options" object.
The second option that you have is to remove the "time" level from your database tree, as it is already present in your "time" field. So new your schema should look like this:
Firebase-root
|
--- Crossfit
|
--- APR_10_2021
| |
| --- Current_Participant: "0"
| |
| --- Date: "APR 10 2021"
| |
| --- Max_Participant: "5"
| |
| --- Time: "10:00-12:00"
|
--- APR_14_2021
|
--- //Data
In this case, you only need to change the way you are adding the data to the database. Your actual "mbase" reference will perfectly fine.
Related
I am using FirebaseRecyclerOptions in calling the database, however, I cannot get all of the data in the database. Here is the structure of the database: database structure the yellow underline is the user id (UID) and below is another node that contains the data that I want to retrieve in the RecyclerView.
Here is a snippet of the code
FirebaseRecyclerOptions<RegisterParking> options =
new FirebaseRecyclerOptions.Builder<RegisterParking>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("RegParkingArea"), RegisterParking.class)
.build();
voPListAdapter = new VoPListAdapter(options);
recyclerView.setAdapter(voPListAdapter);
When you're passing the following two arguments to the setQuery() method:
.setQuery(FirebaseDatabase.getInstance().getReference().child("RegParkingArea"), RegisterParking.class)
It means that the adapter expects to render on the screen RegisterParking objects. If you take a closer look at your database schema, under the RegParkingArea node, you can find UIDs and not RegisterParking objects. The objects that you want to display in the RecycerView exist under each UID. So when reading the data from the database, the Firebase-UI library tries to map each child under the above reference into an object of type RegisterParking, which is actually not possible since the UIDs are strings.
So if you're allowed to change the database schema, then you should either denormalize the data, basically copying the data under another node, or change the actual data into:
db-root
|
--- RegParkingArea
|
--- $pushedId
|
--- uid: "4u9h...XrP2"
|
--- //other fields.
What I have basically done, I have removed a level from the database tree. If you'll use this schema, then you can leave the code as it is and everything will work perfectly fine.
One more thing to note is that if you need to get all parking of a particular user, then you can use the following query:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
Query queryByUid = db.child("RegParkingArea").orderByChild("uid").equalTo(uid);
I am making a SearchView in the search bar to filter all processes that started or ended within a certain date.
I need to get a query of nodes inside processes and codes.
Here is my data structure and what I need to query:
I'm using this for the codes as an example:
//path of all posts
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("codes");
//get all data from this ref
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds: snapshot.getChildren()) {
String hola = Objects.requireNonNull(ds.getValue()).toString();
if (ds.hasChild("process")) {
for (DataSnapshot dsa: ds.getChildren()) {
System.out.println("result"+dsa);
/* if (!isEmpty(Objects.requireNonNull(dsa.child("ended").getValue()).toString())) {
System.out.println("result: "+dsa.child("ended").getValue().toString());
}
*/
}
But I need to obtain the node of other children, preferably without changing the data structure:
I have a FirebaseRecyclerOption where everything is loaded, and I need to only show the holders filtered from the SearchView.
If you're allowed to change the database schema, a more convenient way of storing the data would be to have a flattened structure like this:
Firebase-root
|
--- codes
|
--- $pushedId
|
--- code: 17240
|
--- proces: "Cajones"
|
--- user: "Jose Anton"
|
--- started: longNumberForStarted
|
--- ended: longNumberForEnded
Things I recommend:
Don't use sequential numbers as keys in the database. Use the unique random IDs that are generated by the push() method.
Don't store dates as strings, rather store them as timestamps.
In this way, you'll be able to filter the results as needed. And since you're using timestamps you'll be able to use startAt() or endAt() if you need.
Due to the formatting of the date in the string, it will not be possible to filter or sort the data on the server side. If it was formatted "yyyy.MM.dd a les HH:mm:ss" it would still be possible because they would be in order of magnitude, but arranged this way I can only imagine you reading all the nodes and reordering in a local list ( I don't think it's a good idea).
My suggestion is that you replace the format of this time field to something like a TIMESTAMP from the firebase itself with the server time or if they are custom times, convert them and re-store them.
If you do, you can create custom filters and order them on the server itself, as needed, using orderByChild(), orderByKey(), orderByValue(), limitToFirst(), limitToLast(), startAt(), startAfter(), endAt (), endBefore() and equalTo().
new database structure
This is how I show data for each user using FirebaseRecyclerOptions.
But I want to get all children data for only a specific user with a condition by checking users with UID or any other solution.
Ps : This post was edited many times because of the database structure has been changed
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_pdv, container, false);
recyclerView = v.findViewById(R.id.pdv_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
if (user_id.equals("hZBCb9yk8ycamjoVcISjG2y4ZnI2")){
Query query = FirebaseDatabase.getInstance("https://dtechapp-94795-default-rtdb.europe-west1.firebasedatabase.app")
.getReference().child("commande").orderByChild("user_id").equalTo("hZBCb9yk8ycamjoVcISjG2y4ZnI2"); ;
FirebaseRecyclerOptions<Order> options =
new FirebaseRecyclerOptions.Builder<Order>()
.setQuery(query, Order.class)
.build();
pdvAdapter = new PdvAdapter(options);
recyclerView.setAdapter(pdvAdapter);
return v;
}
}
When you using the following query:
Query query = FirebaseDatabase.getInstance("https://dtechapp-94795-default-rtdb.europe-west1.firebasedatabase.app")
.getReference("pdv").child("user_id");
It means that you are trying to read data from:
rootRef/pdv/user_id
Such a reference actually doesn't exist. Under your "pdv" node there is no child called "user_id", but one called "fP0LLs83MYZqX9BqYO24IX80F3Q2". So you either use:
Query query = FirebaseDatabase.getInstance("https://dtechapp-94795-default-rtdb.europe-west1.firebasedatabase.app")
.getReference("pdv").child("fP0LLs83MYZqX9BqYO24IX80F3Q2");
Or if that UID of the user that comes from a Firebase authentication operation, you can then simply use:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
Query query = FirebaseDatabase.getInstance("https://dtechapp-94795-default-rtdb.europe-west1.firebasedatabase.app")
.getReference("pdv").child(uid);
Edit:
According to one of your comments:
So I want to get data from children of all users at the same time. This is 1st user "fP0LLs83MYZqX9BqYO24IX80F3Q2" I want to get children inside him and at the same time, I want to get children from 2nd user "hZBCb9yk8ycamjoVcISjG2y4ZnI2" and display it in my RecyclerView.
And according to your database schema, please note that you cannot achieve that. There is no way you can get all users having such a schema. Queries in the Realtime Database work on a flat list of nodes. Besides that, you have an unknown key under the UID node, which makes it impossible to query. To solve this, you should consider removing one level in your tree, and add "Amine" and "Zouaoui..." as properties inside each UID node. Your schema should look like this:
Firebase-root
|
--- pvd
|
--- $uid
| |
| --- type: "Amine..."
| |
| --- //Other fields.
|
--- $uid
|
--- type: "Zouaoui..."
|
--- //Other fields.
The code may remain unchanged.
I am currently working on a Rental Car app in Java Android Studio. For the project database, I am using Cloud Firestore. My database is structured like so:
Subcollection:
The first image is represented by the collection of Cars with multiple documents with random ID (each represents a car). Every car has a unique subcollection called bookings where are saved in random ID documents details about bookings made to that specific car (the second image is represented by an example of a booking subcollection).
I am currently working at a "Booking history" section. There, I want to put the current user's booking history (highlighted with red in the second image) in a RecyclerView. I know how to iterate between all cars and their subcollection and put and if(bookedBy == currentUser) condition to obtain only the cars booked by the current user.
But my question is: How can I save those in a RecyclerView? I want to save data highlighted in red (second image) in the RecyclerView if our previous condition is met. I don't know what query to put in the Firestore adapter. I was thinking about saving all the cars booked by the user and their dates in an object or something like this but I can't figure it out. Can anyone help me, please?
Thank you!
According to your database structure, which looks like this:
Firestore-root
|
--- Cars (collection)
|
--- $cardId (document)
|
--- bookings (collection)
|
--- $bookingId
|
--- bookedBy: "bogdanmaris11#yahoo.com"
|
--- endDate: 31 May, 2021...
|
--- finalPrice: 1998
|
--- startDate: 30 May, 2021...
To get all the bookings that correspond to a specific user, a Cloud Firestore collection group query is required. This query looks like this:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query queryByEmail = rootRef.collectionGroup("bookings").whereEqualTo("bookedBy", "bogdanmaris11#yahoo.com");
queryByEmail.get().addOnCompleteListener(/* ... /*);
There are three things to notice. To get the desired results from this query, you might check the email address, as you might have a typo, bogdanmari(u)s11#yahoo.com, where the "u" is missing. Second, it's best to filter the users based on their UIDs and not based on their email addresses, because a user can change the email address at any time, while the UID will always remain the same. And the third one, as I understand, you intend to use the Firebase-UI library, which is good. In this case, the "queryByEmail" should be passed to FirestoreRecyclerOptions.Builder's setQuery() method. However, there might be an issue, because each query requires an index, and the numbers of indexes are limited in Firestore.
According to what you wrote:
I was thinking about saving all the cars booked by the user and their dates in an object or something like this but I can't figure it out.
That's a great idea. That's not about an object, as it more about a sub-collection or a new top-level collection, where you can nest all bookings that correspond to a specific user. In the first case, your schema will look like this:
Firestore-root
|
--- bookings (collection)
|
--- $uid (document) //Not email address
|
--- userBookings (collection)
|
--- $bookingId
|
--- carId: "YI1J ... VSm0"
|
--- endDate: 31 May, 2021...
|
--- finalPrice: 1998
|
--- startDate: 30 May, 2021...
Where there is no need for any email address in the Booking object, however a "cardId" is required, if you need the car data. To get all booking of a single user, the following reference is needed:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference userBookingsRef = rootRef.collection("bookings").document(uid).collection("userBookings");
userBookingsRef.get().addOnCompleteListener(/* ... /*);
And in the second:
Firestore-root
|
--- allBookings (collection)
|
--- $bookingId
|
--- bookedBy: "longUid"
|
--- carId: "YI1J ... VSm0"
|
--- endDate: 31 May, 2021...
|
--- finalPrice: 1998
|
--- startDate: 30 May, 2021...
Where is a simple query (without index) will do the trick:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query QueryByUid = rootRef.collection("allBookings").whereEqualTo("uid", uid);
QueryByUid.get().addOnCompleteListener(/* ... /*);
Pass the first reference or this Query to your "FirestoreRecyclerAdapter" and that's pretty much of it.
I need to add data to an array stored in the database to be like this:
places:
0:"new Item"
1:"new Item",
2:"new Item"
.
.
.
My problem is How to push data in array stored in the Firebase without the need to use a Hashmap? For exemple the next data pushed will result on:
places:
0:"old Item"
1:"vItem",
2:"old Item",
3:"new Item"
I know that if i use the method given bellow, the data will be erased and a new data set will be added,
Utils.eventsRef.child(events.getUid()).child("arrayTicket").setValue(str);
Can someone help me please ?
According to your comments, to be able to add an array into your Firebase realtime database, you need first to convert your array to a List like in the following lines of code:
String[] items = {"newItem", "newItem", "newItem"};
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference arrayTicketRef = rootRef.child("arrayTicket");
arrayTicketRef.setValue(Arrays.asList(items));
The result in your Firebase console will be:
Firebase-root
|
--- arrayTicket
|
--- 0: "newItem"
|
--- 1: "newItem"
|
--- 2: "newItem"