Android Firebase query with range (Above, Mid, Bottom) - android

I just start using Firebase in Android and I wrote query like this.
messageSearchQuery = FirebaseDatabase.getInstance().getReference().child("Message")
.child(conversationID).limitToLast(INITIAL_MESSAGE_COUNT)
.orderByChild("timestamp").startAt(participant.joiningDate).endAt(endAt);
I can only give limitToFirst, limitToLast, startAt, endAt. (I think there is no center)
I need to give timestamp (e.g 10 am sharp) and i wanna query 10 message before 10 am and 10 message after 10 am. (but i don't know when it start, when it end).
Edit
What I want to do is something like this.
messageSearchQuery = FirebaseDatabase.getInstance().getReference().child("Message").
child(conversationID).
orderByChild("timestamp").equalTo(endAt).limitToFirst(INITIAL_MESSAGE_COUNT).limitToLast(INITIAL_MESSAGE_COUNT);
But if I do, it crash like this.
java.lang.IllegalArgumentException: Can't call limitToLast on query with previously set limit!
How shall I do?
My data in firebase is something like this.

You can select a range by combining startAt and endAt, both of which operate on the child you order on. For example if you want messages between 10am and 10pm on a certain date, you'd do:
long timestampOf10am = ...;
long timestampOf10pm = ...;
messageSearchQuery = FirebaseDatabase.getInstance().getReference().child("Message")
.child(conversationID)
.orderByChild("timestamp").startAt(timestampOf10am).endAt(timestampOf10pm)
.limitToLast(INITIAL_MESSAGE_COUNT);
Update: If you need 10 items before 10am and 10 items after 10am, you'll need to fire two queries and merge the results client-side.
long timestampOf10am = ...;
beforeMessageSearchQuery = FirebaseDatabase.getInstance().getReference().child("Message")
.child(conversationID)
.orderByChild("timestamp").startAt(timestampOf10am)
.limitToFirst(INITIAL_MESSAGE_COUNT);
afterMessageSearchQuery = FirebaseDatabase.getInstance().getReference().child("Message")
.child(conversationID)
.orderByChild("timestamp").endAt(timestampOf10am)
.limitToLast(INITIAL_MESSAGE_COUNT);

Related

Firebase Query - how to order by a separate field?

I'm working with an Android App that functions as an instant messaging service, and I'm at the point of pulling the message data through into a RecyclerView. I have my Firebase Query object returning all the messages that match the id of the chat that has been loaded, this is done like so:
Query qChatMessages = mDbRefMessages
.orderByChild("messageChat")
.equalTo(mChatId);
So far so good, and this is returning the collection of messages that I expect. The problem is now that, upon passing them to the RecyclerView to be displayed, they come out in the inverse order of how you would typically expect an instant messenger to display, so the messages are actually getting older as you scroll down the chat.
My message nodes in the database all have a messageTimestamp field associated with them, so this is what I would want to sort the data by. The problem is that I don't seem to be able to find a way of ordering the data by any field other than the one that I'm querying on, or getting the results back from Firebase and subsequently ordering them.
Does anyone know how I can work around this, or if there's some Firebase capabilities I'm not aware of?
Thanks in advance,
Mark
The easiest way is to store an extra piece of data in your message nodes which is the epoch time multiplied by -1: this way you can sort on this field and the query will return the right order.
See this post on how to get the epoch time: how to get the number of seconds passed since 1970 for a date value?
However, note that with your current data structure, you will encounter a problem: you will need to sort on this new data (e.g. with .orderByChild("messageCreationTime")) AND filter for a given mChatId (e.g. with equalTo(mChatId)), which is not possible.
So, you would have to re-structure your database (if this is possible) like this:
- messages
- mChatId
- messageUniqueID <- most probably auto-generated by Firebase
- messageTitle: ....
- messageCreationTime: -1525857044
And you would query by:
Query qChatMessages = databaseReference.child("messages").child(mChatId)
.orderByChild("messageCreationTime");

Cloud Function to sort the Firebase Child from inner child

I need to have one problem sorted out. I want a cloud function, where I need to loop through every Posts that has uniqueID and I want to sort those uniqueID's according to the value of TotalReactions. To me more vivid, suppose, the first post has totalReactions = 5, and second one has totalReactions = 6, then I need to have another RealTimeDatabase "PostArranged" which sorts them in descending order, so second post which has Total Reaction would be in first and then follows the one which has lesser TotalReaction...
Here is how my firebase realtime database looks like:
Posts
-L29TD-nsUYRu3wYcCQl
Caption: "First Screenshot"
CurrentUserReaction: "notreacted"
Image: "https://firebasestorage.googleapis.com/v0/b/nep..."
ReactingUser
<user-id>:"1"
<user-id>:"2"
Time: "13:40:54"
TotalReactions: "2"
Unique: "-L29TD-nsUYRu3wYcCQl"
UserPhoto: "https://firebasestorage.googleapis.com/v0/b/nep..."
Username: "Me"
Any help would be appreciated ..
This is not a good way to do what you want to do. In this method the database has to be sorted to another "ArrangedDatabase" every time a reaction is added which will happen in a high frequency. So it will be very expensive to do this with Cloud Functions.
Instead use orderByChild(), orderByKey(), orderByValue() to sort data when you're querying data.
Sorting data - Firebase documentation this show it quite well.
For anyone who want to do this in your RecyclerViewAdapter provided by Firebase, it is easily done... When you pass in those 4 parameters. Do not pass the database Reference, instead, make a new query, and make sure to sort that thing either by OrderByChild(), OrderByValue() or anything you want to order by... i.e.
In my case, I will do something like this:
q = mDatabaseReference.orderByChild("TotalReactions");
and pass q as parameter inside FirebaseAdapter, like this:
FirebaseRecyclerAdapter<Posts,PostViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Posts, PostViewHolder>(
Posts.class, R.layout.each_post_layout , PostViewHolder.class, q
) {
.
}

SugarORM offset not working

I'm using SugarORM for my Android app. I want to load messages from the SQLite DB but need an offset.
So I load message 5-15 like for pagination.
Unfortunately the offset function doesn't seem to work as expected.
I wrote:
query = Select.from(Message.class)
.where(Condition.prop("MESSAGES").eq(Long.toString(getId())))
.orderBy("timestamp DESC")
.limit("5")
.offset("10");
query.list();
But this only gives me the limit of 5 elements but doesn't use any offset.
Same if I parameterize the query call like this:
List<Message> messages = getAllMessagesQuery.offset("5").list();
Offset isn't working.
Am I doing something wrong? I use the current SugarORM version 1.5
( compile 'com.github.satyan:sugar:1.5')
stating the working offset functionality. So this shouldn't be the issue.
Any ideas how to make this work?
Well, not sure this is the best way to do but at least it's working this way.
If I add the short version to the limit things work fine.
So using the query like this:
List<Message> messages = getAllMessagesQuery.limit("5,10").list();
gives me 10 messages with a 5 message offset.
If that is too dirty, a raw query is also working fine. So you write:
List<Message> messages = Chat.findWithQuery(Message.class, "Select * from Message where Chat = ? ORDER BY timestamp DESC LIMIT 10 OFFSET 5", getId().toString());
Still no idea how to use the offset parameter directly but at least it works this way.

Convert SQL query to Android Azure Mobile Service query

I have a query that works fine in an Azure SQL database, but I'm trying to use it within my Android application and I can't get it to work correctly. It is to find any overlaps in time for bookings. Here is the SQL query with some dummy data, arrival and depart are both integers:
Select * from bourguestMob.tableObjectBookings
where tabObjID = 28
and day = 30
and month = 3
and year = 2015
and ((arrival <= 1600 and depart > 1600)
or (arrival< 1800 and depart >= 1800));
Using the Mobile Service provided, I have to use the query as something like:
tableObjectBookingsTable.where().field("tabObjID").eq(tables.get(i).getId())
.and().field("day").eq(day).and().field("month").eq(month).and().field("year").eq(year)
.and().field("arrival").lt(intTime).or().field("arrival").eq(intTime).and().field("depart").gt(intTime)
That's what I have partially but I think some part of the query needs to be nested to be evaluated correctly.
I think what you want is to change the end of your query to look like so:
.and(field("arrival").lt(intTime).or()
.field("arrival").eq(intTime).and().field("depart").gt(intTime))
It helps me to look at the oData string to check if you get it right, take a look here for some samples of complex queries:
https://github.com/Azure/azure-mobile-services/blob/master/sdk/android/test/sdk.testapp.tests/src/com/microsoft/windowsazure/mobileservices/sdk/testapp/test/MobileServiceQueryTests.java#L724

Parse.com Multiple Count Queries in one Call

I am using parse.com for my app for data storage etc...
I have a quick question, when the user opens my app they are directed to their dashboard, in their dashboard there is a pie chart displaying data. I have in parse a class, in which a colour is an attribute, there are 6 different colours.
I want to display the colour values in the pie chart i.e. 6 red, 3 yellow, 2 blue etc. I researched this through google and came up with this https://www.parse.com/questions/can-i-manage-multiple-count-queries-in-a-single-call which states that it's not possible to have multiple count queries in a single call, however, this was posted 2 years ago and I'm wondering a. if there's been any advances on this since and b. if not what is the best way to go about this.
If I make 6 different calls, and I have to wait until I get the call back from the sixth count query before displaying the pie chart then there could be some delays which isn't good for user experience.
If anyone has any tips on this I'd appreciate it
I'd recommend creating a Cloud Code Function to query the counts in parallel and return the results in one response. I've used that successfully on a project using Parse.
Something like this:
Parse.Cloud.define("dashboard", function(request, response) {
// create each query and start it
var red = new Parse.Query("A").equalTo("colour", "red").count();
var blue = new Parse.Query("A").equalTo("colour", "blue").count();
// wait for them all to complete using Parse.Promise.when()
// result order will match the order passed to when()
Parse.Promise.when(red, blue).then(function(countOfRed, countOfBlue) {
response.success({
red: countOfRed,
blue: countOfBlue
});
});
});

Categories

Resources