I want to find max value from only last 50 nodes. I used to orderByChild and limitToLast methods but it finds max from all nodes, not only from last 50.
Here my db:
And my code:
database = FirebaseDatabase.getInstance();
reference = database.getReference("sensor");
Query query = reference.orderByChild("hum").limitToLast(50);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot myDataSnapshot : dataSnapshot.getChildren())
{
humTemp = myDataSnapshot.child("hum").getValue().toString();
humMax.setText(humTemp);
}
}
public void onCancelled(DatabaseError firebaseError) {
}
});
So, as you see i try to find max value of hum variable from last 50 nodes.
P.S. New nodes are constantly appearing in the database, so the maximum value should change for every 50 values in realtime
If you want the maximum of the 50 most recent nodes, you're trying to order by two properties:
humidity
the time of the node (or its key)
Firebase Database queries can only order/filter on a single property.
In many cases it is possible to combine the values you want to filter on into a single (synthetic) property. For an example of this and other approaches, see my answer here: http://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase. But I don't think that's possible for you.
The best I can think of is to just listen for the last 50 nodes, and then re-ordering them on humidity in the client.
Related
I want to retrieve Firebase data within a range of say 1 week. I can query and get data for a day like today, but how about for a range of say 1 week? This is the code that am currenly using for retrieving data for a given day
String mDate = DateFormat.getDateInstance().format(new Date());
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("expenses").child(onlineUserId);
Query query = reference.orderByChild("date").equalTo(mDate);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myDataList.clear();
for (DataSnapshot snapshot :dataSnapshot.getChildren()){
Data data = snapshot.getValue(Data.class);
myDataList.add(data);
}
todayItemsAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
I cannot find a way of retrieving data for a given range. Someone please help.
The Realtime Database is not designed for complex SQL-like queries.
Not sure if your question refers to grouping results by week. If all you need is a set of results that start and on a certain date and end on another date, you can use startAt(...) and endAt(...) like described in this answer or the spec.
If you need anything more complex than that, you need to
either take all results and filter them in your front end/app code
or use a Cloud Function to do the filtering on the server and
passing the results to the front end.
(Not recommended) You can record the week number (i.e. 45_2020) as a separate field in the document, and filter by that. It's messy and you would have to trust that the front end enters correct info in the field.
I am making an Android app in Android Studio and I want to get specific data from the Firebase. I am trying to search through the Firebase Realtime Database to get all of the Users that have a usercode of 1234 and then getting their name. This is how I have it set up in Firebase:
Firebase Setup image link
Since I am searching for the data where the usercode = 1234 it will return (in the datasnapshot) all of the information about Joe and Lily (since they were the two users that had a usercode of 1234), but it shouldn't return information about Kevin. Here is how I did that:
Query getUsers = ref.orderByChild("usercode").equalTo(1234);
getUsers.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
//User with usercode = 1234 exists
} else {
//User with that Usercode doesn't exist
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The datasnapshot, if converted to a string would have all of Lily and Joe's information I believe.
What I want to do is get the first user's name (Which would be Joe in this case) from that datasnaphot. My code will then use it through a few tests before going to the second user's name(Which would be Lily) and repeating the tests. Also, if there were 100 Users then I would need to repeat it for every one of those 100 that had a user code of 1234, so I probably need something repeatable.
So somehow I need to find the first value of the child's name from all of the Users that have a usercode of 1234 and then repeat until I get all of the names and run the test on all of them.
I am new to Stackoverflow, so please tell me if I am missing any information that would be helpful in answering the question.
---- EDIT ----
I have now figured out how to do this with Firebase Firestore. It has simpler queries and allows you to do more with the results. If anyone else has the same issue that I stated above, Firebase Firestore is something you might want to try out.
When using the following line of code:
Query getUsers = ref.orderByChild("usercode").equalTo("1234");
You are searching through the Users node, all users that have the usercode property set to "1234". This query will always return no results because you are searching for 1234 as a String and not as a number, as it is stored in the database. The correct query should be:
Query getUsers = ref.orderByChild("usercode").equalTo(1234); //No double quotes
I am using a query and having some trouble. I want retrieve value from 5th to 10th. I try to use startAt () the query just doesn't get anything.
public void read(){
Query query = FirebaseDatabase.getInstance().getReference("values").orderByChild("timestamp").startAt(5).endAt(10);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot data: dataSnapshot.getChildren()){
Value upload = data.getValue(Value.class);
mUploads.add(upload);
adapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(MainActivity.this, "Loading Quote failed", Toast.LENGTH_SHORT).show();
}
});
}
Tl;DR: Firebase database queries are cursor based, and not offset based.
When you call startAt() you have to pass in the value of the timestamp you want to start returning results at. You can't pass in offsets, as you are trying to do now.
You current code:
FirebaseDatabase.getInstance()
.getReference("values")
.orderByChild("timestamp")
.startAt(5)
.endAt(10);
Tells the database to:
Find the node called values under the root.
Order each child node by its timestamp value.
Then find a child node with value 5 and start returning results from there.
Stop returning results once it finds a child node with value 10.
As you can probably see, this won't give you any results, since none of your child nodes have a timestamp value between 5 and 10.
As said: Firebase queries are cursor based, meaning they work on knowing something about the node to start at. While many databases paginate based on offsets, Firebase doesn't and you'll need to know the timestamp value of the node to start at.
For example, if you want to start at the node you have opened in your screenshot, and then return the next 5 results, you'd do:
FirebaseDatabase.getInstance()
.getReference("values")
.orderByChild("timestamp")
.startAt(-1590413110563)
.limitToFirst(5);
I have this database:
The candidates collection contains several categories such as president and secretary. It also has totalVotes for each candidate.
I would like to query:
Results by category eg President or Secretary
The candidate with highest 'totalVotes' per category, i.e, the President with the highest votes, and the secretary with highest votes.
Here is my code that is not working:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference candidatesRef = rootRef.child("candidates");
Query specific = candidatesRef.orderByChild("category").equalTo("President");
specific.orderByChild("totalVotes").limitToFirst(1);
specific.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot){
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String firstname = childSnapshot.child("firstname").getValue(String.class);
String lastname = childSnapshot.child("lastname").getValue(String.class);
Long votes = childSnapshot.child("totalVotes").getValue(Long.class);
pres.setText(firstname + " " + lastname+" - "+votes+" Votes");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't swallow errors
}
});
How can I achieve this? Thanks
Unfortunately, there is no OR clause in Firebase. So you cannot filter the candidates on the category property based on multiple values.
There is a solution that might work but only if those values are in a range. In your case, you can get all candidates matching President or Secretary with:
ref.child("candidates")
.orderByChild("category")
.startAt("President")
.endAt("Secretary")
The issue here is that it will also match candidates for other categories whose category is between President and Secretary if it exists. Besides that, you can not limit the query to 1 or 2 because you'll never know which candidate will have the highest number of votes. It might be a president, as well as a secretary.
So, there is no way in the Firebase Realtime Database to pass multiple values into a query. You need to perform separate queries for that and merge the result on the client.
If you consider at some point in time to try using Cloud Firestore, you can find there Query's whereIn(String field, List values) method that can help you solve this issue.
I am trying to understand how firebase data read is count.Is there any way to use hashmap so that whole data read is count as a single read. I have below code currently to fetch data from firebase where I am saving each child value in separate string variable to use in another purpose. Not understanding is it counting as a single read or multiple. is there any better way to do this?
reference.orderByKey().equalTo(bidPosition).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot datas : dataSnapshot.getChildren()) {
if(dataSnapshot.hasChildren() && !bidPosition.isEmpty()){
String eta = datas.child("eta").getValue(String.class);
String riderid = datas.child("uid").getValue(String.class);
String drivierid = datas.child("did").getValue(String.class);
String drivier_ratings = datas.child("dRat").getValue(String.class);
String r_Fare = datas.child("tAmt").getValue(String.class);
}
}
Firebase Realtime Database isn't billed in terms of number of reads. You might be confusing it with Firestore, which is billed, in part, based on the number of documents read.
For Realtime Database, the pricing page makes it clear. You are charged for $5/GB stored (regardless of how it's read), and $1/GB downloaded. How you download/read the data doesn't matter - it's the total volume that counts. So there is really no way to significantly optimize a read or query operation that fetches some data.