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
Failed to Import New Gradle Project: Failed to Find Build Tools Revision *.0.0
How to Sort Alphabetically While Ignoring Case Sensitive
Android Days Between Two Dates
Passing a JavaScript Object Using Addjavascriptinterface() on Android
Android: How to Disable List Items on List Creation
Android Studio - No Jvm Installation Found
Android App in Eclipse: Edit Text Not Showing on Graphical Layout
Deserializing Generic Types with Gson
How to Reliably Simulate Touch Events on Android Without Root (Like Automate and Tasker)
Android Change Material Elevation Shadow Color
Issue When Using a Custom Font - "Native Typeface Cannot Be Made"
Cordova Could Not Reserve Enough Space for 2097152Kb Object Heap
How to Convert Date to a Particular Format in Android
Alertdialog from Within Broadcastreceiver? Can It Be Done