Ordering after childrencount in Child node in firebase - android

Is there a way to order after the amount of childnodes a child has in firebase.
Query query = databaseChildRef.orderByChild("likes").limitToLast(10);
Likes are stored as an Long here so this one is being queried fine, but when I try to retrive a list of the child with the most comments (List)
Query query = databaseChildRef.orderByChild("comments").limitToLast(10);
...the same principle doesn't apply.
Is there a way to order after the count of child nodes in child "comment".
Thanks.

The Firebase Database does not support any server-side aggregation operators. If you want to order on the number of comments, you'll need to store a commentCount property and keep that up to date.

Related

Firestore whereIn query documents are randomly ordered

I have a collection of groups and a collection of users, each user document has a collection of ids to the group he has joined. each group id document has one field (timestamp) to mark when a user joined a group.
I want to get the list of groups the user has joined in ordered by timestamp descending.
First I am getting the groups ids from the sub collection inside user document and they are ordered by timestamp, Then, I am using whereIn() to get the groups objects from the groups top level collection by passing 'groupsIds' ArrayList.
Here is the problem, resulted documents from whereIn() are randomly ordered. I want them to be ordered according to 'groupsIds' list. Can firestore do that for me ? Or I will have to do this myself ?
If you can't tell Firestore how to sort the documents using orderBy, you're going to have to sort the documents yourself. And in this case, you are going to have to do that.

Firebase Realtime database Array query issue [duplicate]

This question already has an answer here:
Firebase query if child of child contains a value
(1 answer)
Closed 3 years ago.
I need a firebase query to filter the list based on the value of an array.
if any of the index of GID(Array) contains the given key. e.g my key is YsGMyfLSGRNHxDWQmhpuPRqtxlq1 and one node's GID have that on 0th index and other have that on 1st index. So these two lists need to be returned.
Currently, I can only get the one at 0th index using the code
//userID = YsGMyfLSGRNHxDWQmhpuPRqtxlq1
firebaseDatabase.child("Groups").queryOrdered(byChild: "GID/0").queryEqual(toValue:userID)
When I try to combine the query I am getting errors.
I don't know about your database structure, But I can explain that There is a limitation in Firebase Realtime database that you can only order by 1 child.
So now if we require to order by 2 Childs we can combine 2 nodes and make it 1 node and can apply order by query on it. For example
If we have username & email fields we can make a new field username_email and can apply order by on it.
Like
user: {
username: "john",
email: "john#g.com"
username_email = "john_john#g.com"
}
Now we can write
firebaseDatabase.child("user").queryOrdered(byChild: "username_email").queryEqual(toValue: "john_john#g.com");
There is no way you can filter your groups based on a value that exist within an array. If you want to query your database to get all groups a particular user is apart of, then you should consider augmenting your data structure to allow a reverse lookup. This means that you should add under each user object the groups in which that user is present.
This means that you'll need to duplicate some data, but this is not a problem when it comes to Firebase. This is a quite common practice, which is named denormalization and for that, I recommend you see this video, Denormalization is normal with the Firebase Database.
When you are duplicating data, there is one thing that need to keep in mind. In the same way you are adding data, you need to maintain it. With other words, if you want to update/detele an item, you need to do it in every place that it exists.
However, what you need is actually allowed in Cloud Firestore. Its array-contains operator allow you to filter documents that have a certain value in an array. For more on this topic, please see the following post:
Better Arrays in Cloud Firestore.

Android's Firestore to join 2 collections into a recycler view

I have a users collection with uId, name, photo
I have a visits collection with uId, userId, location
I have a recyclerview in which I want to show the location with the user name and photo
Can I use the reference field type? If so, how will Firestore know to link visits.userId == users.uId ?
Maybe I first need to query all the visits and then query the relevant user but 2 things:
It means querying a lot of times.
I didn't understand how to collect the joined collection into the adapter, which is based on one query?
Please advice
Thanks
current code
visitsList = db.collection("visitsList");
Query query = visitsList.whereEqualTo("userId",prefs.getString("id","")).orderBy("visitDate", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<AVisit> options = new FirestoreRecyclerOptions.Builder<AVisit>().setQuery(query, AVisit.class).build();
adapter = new VisitsListAdapter(options, VisitsListActivity.this);
RecyclerView rv = findViewById(R.id.rvVisitsList);
rv.setHasFixedSize(true);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(adapter);
The code is a simple query from the collection, not sure how to get the name and photo from the userId field in that collection.
Can I use the reference field type?
Yes, you can use a reference field.
If so, how will Firestore know to link visits.userId == users.uId ?
Firestore results always comes from a single collection (at the moment). It does not automatically join the document from the users collection when you're reading from the visits collection. You will have to do this yourself.
That indeed means you'll be executing multiple reads, but it's often not nearly as slow as you may think. See Google Firestore - how to get document by multiple ids in one round trip?
Update: To show data from the user profile in a list of visits, there are two main options:
load the additional user document in populateView or with a custom parseSnapshot implementation.
duplicate the relevant user data in the visits collection (which is quite normal in NoSQL databases). Also see Alex' answer here: indexed query with FirestoreRecyclerAdapter.

Firebase query orderByChild

I want to perform a query to a firebase database.
My database is as follows:
I want to query "paymentStatus" by orderByChild value "paid".
How will my query code look? The below code not reading.
Query query = FirebaseDatabase.getInstance().getReference().child("Visits")
.orderByChild("paymentStatus").equalTo("Paid");
Thank you in advance.
Firebase database queries function on a list of child nodes, not on a tree. The database takes each direct child node under the location you query and then sorts/filters on the property you indicate.
There is no property paymentStatus directly under the child nodes of Visits, because the paymentStatus is one level deeper. That means that in your current data model, the query you want is not possible. If you want to filter visits by paymentStatus you will need to ensure that you have a single, flat list of visits.
Also see my answer to Firebase Query Double Nested.

Firebase query implementation

If we query data from Firebase on a key for a child node, does it downloads the whole child node and filter data in the application or it downloads the query specific data? i.e. the filtered data
String myUserId = getUid();
Query myTopPostsQuery = databaseReference.child("user-posts").child(myUserId).orderByChild("starCount");
myTopPostsQuery.addChildEventListener(new ChildEventListener() {});
myTopPostsQuery will sort data according to starCount and I will receive data in the addChildEventListener() I want to know that whether this data is being filtered inside my app after receiving or my app downloads only the filtered data from the Firebase.
If you use a filter in your query you will download the query specific data without any operation executed on the client side.
Keep in mind that:
You can only use one order-by method at a time. Calling an order-by method multiple times in the same query throws an error.
You can combine multiple limit or range functions. For example, you can combine the startAt() and endAt() methods to limit the results to a specified range of values.
For any other info take a read here
You get the data already filtered. When you use a query, let say, limitToLast(10) you get only those 10 elements. This is happening also in your case with orderByChild("starCount"). In your SnanpShot will find only those filtered elements. Please visit official doc for more details.
Hope it helps.
Based on the code you pasted here, your query will just retrieve all the posts for the database path user-posts/<id> with an ordered manner which means that there is not filter. But still you will get back all the available posts under the path you are querying. It can be a "semi-filter" as it will find only the posts which include starCount field
The best thing is to filter during your query in order to retrieve back exactly what is needed and not everything as you are doing right now, imagine that this list of posts can be really big so you will have a big issue with performance later.
Read the following section here about sorting & filtering.
https://firebase.google.com/docs/database/admin/retrieve-data#orderbychild
Apart from that consider to add an index in userId field for speeding up your query.

Categories

Resources