How to Read Firestore Sub-Collection and Pass It to Firestorerecycleroptions

how to read firestore sub-collection and pass it to FirestoreRecyclerOptions

The problem in your code lies in the fact that the name of the fields in your CommentModel class are different than the name of the properties in your database. You have in your CommentModel class a field named comment but in your database I see it as Comment and this is not correct. The names must match. When you are using a getter named getComment(), Firebase is looking in the database for a field named comment and not Comment. See the lowercase c letter vs. capital letter C?

There are two ways in which you can solve this problem. The first one would be to change your model class by renaming the fields according to the Java Naming Conventions. So you model class should look like this:

public class CommentModel {
private String comment, commentDate, profilePic, commentUser;

public CommentModel() {}

public CommentModel(String comment, String commentDate, String profilePic, String commentUser) {
this.comment = comment;
this.commentDate = commentDate;
this.profilePic = profilePic;
this.commentUser = commentUser;
}

public String getComment() { return comment; }
public String getCommentDate() { return commentDate; }
public String getProfilePic() { return profilePic; }
public String getCommentUser() { return commentUser; }
}

See in this example, there are private fields and public getters. There is also a simpler solution, to set the value directly on public fields like this:

public class CommentModel {
public String comment, commentDate, profilePic, commentUser;
}

Now just remove the current data and add it again using the correct names. This solution will work only if you are in testing phase.

There is also the second approach, which is to use annotations. So if you prefer to use private fields and public getters, you should use the PropertyName annotation only in front of the getter. So your CommentModel class should look like this:

public class CommentModel {
private String comment, commentDate, profilePic, commentUser;

public CommentModel() {}

public CommentModel(String comment, String commentDate, String profilePic, String commentUser) {
this.comment = comment;
this.commentDate = commentDate;
this.profilePic = profilePic;
this.commentUser = commentUser;
}

@PropertyName("Comment")
public String getComment() { return comment; }
@PropertyName("CommentDate")
public String getCommentDate() { return commentDate; }
@PropertyName("ProfilePic")
public String getProfilePic() { return profilePic; }
@PropertyName("CommentUser")
public String getCommentUser() { return commentUser; }
}

Don't also forget to start listening for changes.

P.S. In your class, it should be:

this.commentDate = commentDate;

and not:

commentDate = commentDate;

how to get data from firestore sub-collection

You can get the data from the collection by accessing the subcollection inside the document like this

Firestore.instance.collection('singers').document('aryana sayeed').collection('song list').snapshots()

or

Firestore.instance.collection('singers/aryana sayeed/song list').snapshots()

Firestore Querying a collection with a sub collection

You need to run two separate queries.

query = collectionReference.whereEqualTo("Product", Constants.PRODUCT_NAME);

After this, you will know the DocumentID, you need to use this docId to point to the sub-collection, this is the pseudo code:

collectionReference.doc('ID from previous query').collection('Photos');

Android Firestore subcollections into RecyclerView

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.

How to query a Collection after a specific Document in Cloud Firestore with Android?

There's no way to extend a query across multiple subcollections. A query must be contained within a single collection or subcollection. So, you're correct in guessing that you'll need to duplicate data in order to perform your query.

How to display a document with its subcollections from Firestore in a RecyclerView with Android?

But I am not able to retrieve a document with its subcollections and put it inside an object.

There's no way you can achieve this. The queries in Firestore are shallow, so it is allowed to only get documents from the collection that the query is run against. Furthermore, there is no way you can get a document together with the nested subcollections in a single go. You can get the document and then run separate queries for each and every subcollection.

Another possible solution might be to use Firebase Realtime Database, where when you download a node, you download it together with all the data that exist beneath that node.

I use AsyncTask to do the background work of querying all the posts of the user.

The Cloud Firestore client already runs all network operations in a background thread. This means that all operations take place without blocking your main thread. Putting it in an AsyncTask does not give any additional benefits.



Related Topics



Leave a reply



Submit