What is the better structure between collection and subcollection in Firestore? - firebase

I am working on a social Flutter app where there is a section for posts. Each post can have comments and each comment can have replies which are different from comment in class level. I am using Firebase Firestore as my backend. As the official docs for Firestore states that there are three ways to structure our data as follows: top-level collection, document and subcollection (collection inside of a document). In my app, for posts I have a top-level collection called posts which consists all of the posts. Now that each post can have thousands of comments, so storing comments inside each post document as a map value is not a good idea as it will cross the limit of 1MB per document and also adding and deleting a comment would be so hard. So now I can not decide whether I should create a top-level collection for comments or a subcollection for comments in each post document. It's the same for replies of each comment. Should I again create another top-level collection for replies or a subcollection for replies in each comment document? I strongly appreciate your advice and help!

So now I can not decide whether I should create a top-level collection
for comments or a subcollection for comments in each post document.
There is no difference from a technical or performance perspective since:
A Firestore query performance is proportional to the size of your result set, not your data set (i.e. the number of docs in the collection);
You can, with Collection Group queries, query all the documents of all collections with the same ID (i.e. comments or replies).
The main difference is probably that in the Firestore console you can easily display the sub-collection of a specific post.
Note that if you choose to go for root collections for comments or replies you should not forget to save the parents IDs in these children docs in such a way you can query the one corresponding to a specific parent.

Related

Best practice to store and query likes/dislikes of a post in firestore

I am building an app where users can like and dislike posts. Now, in firestore, I am creating a liked_by and disliked_by collections inside each post document, where I add the userId of the users who liked/disliked a post as document IDs.
Now, when showing posts to a user in the app, I have to check if each post has been liked or disliked by the current user, so that I show them that they have already liked/dislike the post. This means I have to perform 3 queries for every post (one for the post contents, one to check if the user's ID is in the list of the liked_by collection, and another to check if the user's ID is in the list of the disliked_by collection). That seems like too many queries per post, especially considering that the likelihood of the user actually having liked/disliked a post that they're seeing is low.
Is there a more efficient way of doing this?
Other options I have thought about:
Keeping the liked/disliked list of user IDs in an array field within the post document. The downside here is that a post document will be too much text data when fetching, and also documents have a limit of 1MB so it's not fully scalable.
Creating a liked/disliked collections in each users document and keep a list of post IDs that a user has liked/disliked. The one downside here is that overtime this list of documents will grow and I'll have to always fetch all documents every time at first. So if the user has liked/disliked 300 posts overtime, then from that point forward, i'll always fetch all 300 documents to see if a post they are looking at is within the list. If they only ended up looking at 30 posts, then this wouldn't be worth it, I could've queried the likes/dislikes separately and only fetched 90 documents (3 queries for each post as mentioned in second paragraph), instead of the 300 plust the 30 posts.
Thanks

How to access virtual documents in Firestore through Firebase SDK?

I am a beginner and my firestore database has a collection which has documents and each document has a subcollection without any other fields. I can't find a way to access the ID of the empty document and get the subcollection associated with the doc using the SDK. I could do it on console but I have to too much to do and cannot also make changes to my application for now so I need to use the SDK. Please suggest me some way to access them like the console.
If you know how the CollectionReference of the sub-collection, you can easily get the parent DocumentReference with parent property of the CollectionReference. From the DocumentReference you just need to use the id property.
You didn't share much details on your data model, so it is difficult to give more guidance on how to find the CollectionReference. Mark's answer presents some possible approaches.
So, I used collection group query(collectionGroup) to query the documents in the subcollections(which have the same ids) and found the IDs of the parent document by the parent property.
Huge thanks to #mark carlton and #Renaud Tarnec for these suggestions.
CASE 1: If the subcollections are queried across multiple documents, you could use a collection group query which queries collections of the same name regardless of their position in the hierarchy. This way you don't actually need to know the ID of the document
CASE 2: Use a document ID you will remember for such a case as opposed to having a UID for the ID. This was your queries make much more sense to you

Firestore/Angularfire get collection of docs and subcollection of those docs

Is there a way with Firebase or Angularfire2 to get all the docs in a collection, as well as, one or all of the immediate subcollections.
For example, if I have a collection of categories where each category has a name, as well as a subcollection of subcategories, is there a way to get all the categories with their subcategory collection?
In my head, I'd want to do something like this:
afs.collection("categories").withSubcollection("subcategories");
Another idea I was thinking of that would work but isn't possible, would be to use a wildcard in the path like this:
afs.collection("categories/{categoryId}/subcategories");
I know neither of these are possible, just wanted to see if there was a way to do what I am showing.
At the moment, I store the subcategories in an array on the category document, but documents have a maximum size, a category could theoretically have an unlimited number of subcategories.
Read operations in Firestore are always shallow, and only return document(s) from a single collection. To read documents from multiple collections, you'll need multiple read operations.
The only exception to this is when the collections you want to query have the same name, in which case you can use a collection group query.
I honestly doubt if storing the categories in a subcollection is worth the hassle. While a document has a maximum size, it's 1MB. I'd highly recommend doing the path on how many categories you can store in that, and whether that is a reasonable limit for your app.

How to share a post in twitter clone app using Firestore as a database?

I have a Firestore data structure and a document where all my followers can see the recentPosts of mine by querying the collection of documents based on the users field of the document where querying users name is present just like below.
my question is how to share a post of others to my followers, currently i am duplicating the shared post to my recentPostsand my seperate Collection of posts documents, but what if a user deletes the post and the post was shared by million users? i have to delete all the shared posts, is there a better solution?
Given your choice in data model, having to delete the duplicated posts is pretty much the normal solution. I also don't see this as problematic, given that:
You've already written the duplicate post to all these followers to begin with, so the delete is just another write.
Deletes and other writes are relatively uncommon in most applications. If not, consider whether you should really be duplicating the data to all followers.
You could choose to implement this with a global list of deleted posts, that each client then reads. But at that point you're making the code that reads data more complex to prevent writes, which is typically not the best approach when using NoSQL databases.

How to copy a collection as subcollection in firebase?

I have a users collection and articles collection. Every user starts with all the articles in articles collection which I store as sub-collection of the user and I only keep the articles which the user has not read. When the user reads an document from article collection, I remove it from user's sub-collection. The problem is when a new user signup, I have to fetch all the documents in articles collection and copy over to user's sub-collection which is unnecessary bandwidth usage. Is there any way to minimise it? Is my database model is good enough?
I am more familiar with firestore than firebase but I can give you some ideas until someone better comes along!
You can avoid copying the entire articles by just keeping a list of article IDs for each user that can be used to look up the article in the main list. This list could either be a sub collection or just an array in the user document.
If you were really concerned about bandwidth you could store a list of all the articles in a top level document (that would have to be updated every time you added or removed an article). This stinks a bit of duplication and makes the model more fragile (you must keep two things in sync) but would allow you just to copy this small list instead.
A different approach, if your articles tend to be read in order, is that you could combine a list of unread articles with another field that indicates the latest read article - anything after this article can be considered unread even if not in the list. A new user would then just have this new field set to 0 to indicate no articles read. This also means you wouldn't need to add new articles to all users as each user would check for any articles newer than this new field when they access your service.
Hopefully this can give you some ideas to try and play around with!

Resources