On my Android app, I have a calendar. When I click a date, I want to just show the items from that selected date. In other words, filter all other items out of the RecyclerView adapter and just show the ones for the selected Date.
Currently, when the activity opens, it just displays all items:
Query query = FirebaseDatabase.getInstance().getReference().child(FB_SUBJECTS).child(FB_PACKS)
PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPrefetchDistance(5)
.setPageSize(10)
.build();
//Initialize FirebasePagingOptions
DatabasePagingOptions<FB_Model> options;
options = new DatabasePagingOptions.Builder<FB_Model>()
.setLifecycleOwner(this)
.setQuery(query, config, snapshot -> {
FB_Model model = snapshot.child(FB_PROFILE).getValue(FB_Model.class);
addMarkerToCalendarView(getMilliFromDate(model.getstart_date()));
return model;
})
.build();
That will return all items at subjects/packs. Then from this query, I get some data from <userId>/profile/, like start_date and end_date, eg subject/packs/001/profile/start_date
Here's some sample data for start_date and end_date:
end_date; "05-04-2019"
start_date: "01-04-2019"
So, my problem is I want to filter these items, BUT I'm using FirebaseRecyclerPagingAdapter but that only pulls down a certain number of items at at time, eg 20. So I can't store all the results in one big list and filter them easily. So I'm relying on some built in functionality of Firebase.
Is it possible to alter my Query to achieve this? I know there's a startAt() and endAt() but not sure if they suit FirebaseRecyclerPagingAdapter.
So really what I need is a SELECT * from profiles where startDate = x and endDate = y;
Is that possible with the realtime DB on Android?
Thanks.
Is it possible to alter my Query to achieve this?
Sure it is but with some changes. As I see, you are storing in end_date and start_date properties the date as a literal String and this is not how you deal with dates in Firebase. So you should store the date as a Timestamp, which is basically a number, a long value. To see how you can achieve this, please see my answer from the following post:
How to save the current date/time when I add new value to Firebase Realtime Database
In the end, simply pass the needed timestamps to the startAt() and endAt() methods.
I know there's a startAt() and endAt() but not sure if they suit FirebaseRecyclerPagingAdapter.
You can pass to FirebaseRecyclerPagingAdapter any kind of query, including the one that has calls to startAt() and endAt() methods.
Related
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.
I've been struggling with this for days now and can't work out what's wrong. The thing is, I am not getting errors at the moment. Im just not producing the result I hoped for. I am trying to read from a specific record in my sqlite database where the data is a week ago today - I am trying to get the weather on this day, which is in my database. Here is my DB code for the method I am using:
public long homepageTB(){
LocalDate now = LocalDate.now();
LocalDate lastWeek = now.minusDays(7+now.getDayOfWeek().getValue()-1);
LocalDate currentDate = now.minusDays(now.getDayOfWeek().getValue());
String[] lweek = new String[1];
lweek[0] = String.valueOf(lastWeek);
String lastwk = String.valueOf(lastWeek);
long rv = -1; //<<<< default return to indicate no such row
SQLiteDatabase DB=this.getReadableDatabase();
Cursor cursor=DB.rawQuery("select weather from dailyQuiz1 where date =?",lweek);
if (cursor.moveToFirst()) {
rv = cursor.getLong(cursor.getColumnIndex("weather"));
}
System.out.println(lweek[0]);
System.out.println(rv);
return rv;
}
At the moment, this correctly returns the data week ago in format: 2022-01-31
and returns rv: -1 (which means it can't find the record). However, the record is there in my database:
So realistically I don't want -1 to be returned as I would want the variable in another class I am calling it from to now hold the value of the weather, which you can see in my database is 'Rainy'. Any ideas what I've done wrong or what is a better approach? I feel it will be something so obvious but I've been trying so many things for the past few days :( Thanks for the help
With the exception that you will have an issue with the returned value being 0 if the data is found
i.e. you are getting a long from a text value when using rv = cursor.getLong(cursor.getColumnIndex("weather")) so instead of crashing when trying to convert Rainy to a long 0 is given.
What you have shown works as expected. That leaves the issue to probably be that the database does not in fact contain a row where the date column does equal the String 2022-01-31.
You need to ensure that what is in the actual database being used is as expected (your image appears to be from a tool rather than the actual database and often issues are due to differences).
So in Android Studio run the App and get to a point where it is awaiting for user interaction. The click on App Inspection do you see the same data? e.g. it should look like (not all columns have been included in the example):-
If not then your issue is that the data is not being added as expected and that needs to be corrected.
Otherwise click on the Query Icon
Enter and run SELECT length(date), * FROM dailyquiz1 WHERE date like '2022-01%' e.g. :-
if the first column returned is > 10 then there is an issue with the data that is being stored, as it contains additional data.
if the first column returned is < 10 then you are storing data that is shorter than it should be.
if no data is returned then the data stored is even further away from what it should be.
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.
I have an app where are few users. Each user can save item to firebase. But when a user save an item that item save under a date time child, and under user
name.
That's how my items are saved and users available
And instead of numbers (0,1,2) I want to appear date time and user name. Hope the question is ok i couldn't find any tutorial.
Here is my code :
databaseReference = FirebaseDatabase.getInstance().getReference("jsonData").child("listaVanzatoareProduse");
databaseReference.setValue(Util.getInstance().getVanzatorProduse());
Util.getInstance().getVanzatorProduse().clear();
The .child() method creates a new node if it doesn't exists. so you can simply do:
databaseReference = FirebaseDatabase.getInstance().getReference("jsonData").child("listaVanzatoareProduse").child(dateTime).child(userName);
databaseReference.setValue(Util.getInstance().getVanzatorProduse());
I am wondering how to query the database using the model in play 2.0 with a query like the one I listed below. I didn't see an option to pass in direct sql into the play framework 2.0.
I am trying to get a list of the expenses from a particular month.
SELECT * FROM Expensesdb.expense
WHERE month(expense.purchase_date) = 01
The option I see is to query for all the expenses and then parse each one for the month they are listed using the Date object.
I think there should be an efficient way, I can't seem to find a way to do this using ebean with Java play framework 2.0 to perform this query.
Update
Thanks Nico, I tried the exact code you have, with DateTime and I tried to use the code below, it doesn't return any Expenses. Am I doing something wrong?
Calendar calendar = Calendar.getInstance();
calendar.set(2012, 0, 01);
Date startDate = calendar.getTime();
calendar.set(2012, 0, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
Date endDate = calendar.getTime();
List<Expense> expenses = find.where().between("purchaseDate", startDate, endDate).findList();
return expenses;
I see two options:
1 - Using Ebean mapping
The idea is to search the expenses between the beginning and the end of the month, something like:
Datetime firstDayOfMonth= new Datetime().withDayOfMonth(1);
Datetime lastDayOfMonth = new Datetime().dayOfMonth().withMaximumValue();
return finder.where()
.between("purchaseDate", firstDayOfMonth, lastDayOfMonth).findList();
2 - Using RawSQL
For this, please take a look at the Ebean documentation.
The main drawback of raw sql is that this code will not be portable for different SQL servers (if you don't plan to use several db engine, it will not matter).
+1 for #nico_ekito
On the other hand, while you are suggesting getting all rows from DB and then parsing them in the loop, I'd rather suggest to parse them... while creating and store in format easier to search and index. Just create additional column(s) in your DB, and override save() and/or update(Object o) methods in your model, to make sure, that every change will set the field, ie use String purchasePeriod for storing string like 2012-11;
you can find then:
# in November of ANY year
SELECT * FROM table WHERE purchase_period LIKE '%-11';
# in whole 2012
SELECT * FROM table WHERE purchase_period LIKE '2012-%';
# in December 2012
SELECT * FROM table WHERE purchase_period LIKE '2012-12';
alternatively you can divide it into two Integer fields: purchaseYear, purchaseMonth.
For the first scenario the overriden save() method in the Expense model can look ie like this:
public void save() {
this.purchaseDate = new Date();
this.purchasePeriod = new SimpleDateFormat("yyyy-MM").format(this.purchaseDate);
super.save();
}