Learn how to use the new Collection Group Query feature to join subcollections. Great for hierarchical or deeply-nested data structures like threaded reddit-style comments https://fireship.io/lessons/collection-group-query-firestore/

#firebase

Take the firebase quizzes 🤓

iOS https://itunes.apple.com/us/app/fireship/id1462592372?mt=8
Android https://play.google.com/store/apps/details?id=io.fireship.quizapp

Upgrade to Fireship PRO at https://fireship.io/pro
Use code lORhwXd2 for 25% off your first payment.
2024-02-04T06:45:53.036Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
d58c935a-a971-451d-af3a-0c9a08a3d4b6
b715f10a31c7176f644b6cfe5aaa3407807fc41a36226a895be9a2d775246aa0
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
1 of the most frustrating things about Firestore is modeling your data as a hierarchy of subcollections, because even though this is a very intuitive data model that represents relationships very well.
It's not very practical because you can't join these collections together to query them at the same time.
Well, at least that was the case until now.
Firebase just recently released a new feature called Collection Group Queries.
In today's video you'll learn how this new feature makes working with sub a lot more intuitive.
And we'll put this new feature to use to make a deeply nested threaded comments feature with Angular.
If you're new here, like and subscribe, and you can grab the Source code from FireShip IO.
And if you're building a product with Firestore, consider becoming a pro member to get access to the data modeling course.
Let's first take a look at the problem that we can now solve with a Collection group query.
Let's consider the very typical data model of blog post comments.
Users can have many comments, posts can have many comments, and a comment belongs to a post and a user.
We'll have at least 2 screens in the app that we want to fill with data.
Most commonly, we'll want to show all of the comments associated to a given post, But we might also have something like a user activity feed that queries all the most recent comments from that user.
Reddit would be a perfect example of this.
And Reddit also allows users to respond to comments so you can get these deeply nested threads of comments, which is another problem that is much easier to solve with collection group queries.
Now if you've been using Firestore for a while, the most likely way that you've modeled a relationship like this was to create a root collection of comments and then save a Post ID as well as a user ID on each individual comment.
The reason you wouldn't make comments a sub collection of a post is because you then wouldn't be able to query all of the comments created by an individual user.
And that's the exact problem that collection group solves because it allows you to group all the collections in the database based on a shared name or ID.
And it doesn't matter how deeply nested these collections are, they can be nested up to a 100 levels deep and still be included in a collection group query.
And that's extremely useful when you have a complex hierarchy of data like you would with Reddit comments.
In this example here, we have a collection of posts And then you can see an individual demo post has a sub collection of comments.
The comment document itself has a user ID and the comment text.
Now in order to create a Reddit style hierarchy, we can also give each individual comment its own sub collection of comments.
The only important part for the query is that the sub collection shares the same name, we can just continue to follow this pattern until we hit Firestore's limit of 100 nested subcollections.
So this data model preserves the hierarchy of comments and replies, but now let's take a look at how we can group these collections together to query them based on the user ID and also some of the caveats that you'll run into along the way.
First, let's take a look at some vanilla JavaScript using the Firebase SDK version 6 point o or greater.
To join all of these subcollections together, we just call database collection group with the name of the collections, which in this case is comments.
That's going to find all of the comments collections throughout the entire database and join them together, and then we can make queries across them just like we would with a normal collection.
For example, we can call where the user equals a certain user ID to filter just by that user, Or we might want to order by a created at timestamp.
But if you try to actually run this query in your own code, the first thing you'll see is this Firebase error missing or insufficient permissions.
That's because there are some special rules in place for collection group queries.
First of all, at the very top of my rules, you'll notice that I'm enabling the rules version 2.
In this example, we just wanna go ahead and make all of the comments readable and writable.
So we'll say path equals star star slash comments, And that will allow access to any document in a comment sub collection.
But in a real app, you would most likely lock down right access for the logged in user with a matching user ID.
So that's going to take care of the permission error, but now we're going to see an error that says that we need an index for this query.
That will also give you a link directly to the Firebase console to create the index, So go ahead and click on that.
Unlike a regular collection query, you'll need an index for every collection group that is filtered by a certain property.
That'll take a minute or 2 to set up, but once it's done, you should be able to make this query successfully.
Now that you know how collection group queries work, I want to show you how you can actually make use of these deeply tested data structures in a real world JavaScript application.
We'll be using Angular, and at the time of this video, you'll need to install AngularFire using the next tag.
And what we're building is just the front end application that can query the data that I showed you earlier in the data model.
First, we query the top level sub collection associated with the post.
Then from there, the user can lazily load additional comments or replies to an individual comment by clicking this more button.
And another nice thing about this data model is that we can query the data very efficiently and as we'll see, we can do so in a way that doesn't require any complex query code.
And we'll also create a second view that uses the collection group query to flatten all of this data out for a single user.
The first thing we'll do is go into this post component, which is responsible for displaying the post itself as well as the sub collection of comments nested under it.
Now to get the first level of comments that are nested under a post, All we have to do is make a reference to that subcollection in the database, and then we'll make sure to call snapshot changes here as opposed to value changes.
And the reason we call snapshot changes here is because it contains additional data about the document itself like the ID, but more importantly, the full path to the document in the database.
Now in the component HTML, we can go ahead and loop over that observable of snapshots, and then we'll pass each individual snapshot into this app comment component, which we'll create in the step.
Setting up an NG 4 loop with the async pipe will automatically subscribe to that observable to retrieve the items from the database, then we'll handle all the presentation logic in this child comment component.
In the comment component, the first thing we'll do is set up the input property so we can pass the document snapshot from the parent to the Tiled.
The query document snapshot contains all the data from that document in the database, but it also contains the document ID and the full path to that document in the database.
But each individual comment might also contain its own subcollection of comments, which we'll go ahead and call replies here as the property on this component.
Now we can come down here to n g on init to define all these properties.
The ID and the data just live directly on the document snapshot.
We can get the full path to the document as a string by calling comment ref path.
We need this full path to make a reference to the sub collection.
We can make that reference by calling database collection, then passing in the path and appending comments to the end of it.
That'll give us a reference to the sub collection of comments nested under this particular comment, Then we can use snapshot changes to get the actual data snapshots as an observable.
Now the last thing I'll do is add a method down here that allows the user to flip the show property to true And that will be fired when the user clicks the show replies button.
In the template, I'm gonna go ahead and show the full path to the document in the database as well as the actual text of the comment.
Then I'm going to set up a div here with n g f, so this will not be rendered unless that show property is true.
And then inside that div, I'm going to add the app comment template, which is the same template that we're defining right now, so we're calling it recursively.
And this works really well because the observable won't be created or subscribed to until the show property equals true.
That gives us a very easy way to lazy load data on a deeply nested thread.
Now if you wanted to traverse the entire tree of comments by default, all you would have to do is set the show property to true and it would fetch every single comment nested under the starting point.
And that's all it takes to access deeply nested data like this, so using a recursive pattern like can be very powerful and very simple at the same time.
And the great thing about a collection group query is that it's now practical to do this because we can also make additional queries Cross this data without having to worry about it being deeply nested.
And that actually becomes the easiest part of all because all we have to do now is go into our user comments component, then we call a database collection group, Point to the comments collection name and then just call snapshot changes with whatever query logic that we want to apply there.
And that will give us all the comments for that user, but without Out the hierarchy structure, so we get them flattened out in just a regular array that we can loop over.
Overall, the collection group query is a very simple feature, but one that Adds a ton of flexibility to data modeling in Firestore.
I wouldn't recommend going and restructuring your existing database, but it is definitely a feature you should consider going forward.
I'm gonna go ahead and wrap things up there.
If this video helped you, please like and subscribe and consider becoming a Pro Member at Fireship IO.
You'll get access to the full Firestore Data Modeling course as well as a bunch of other exclusive content.
Thanks for watching and I will talk to you soon.

Speaker 0: 1 of the most frustrating things about Firestore is modeling your data as a hierarchy of subcollections, because even though this is a very intuitive data model that represents relationships very well. It's not very practical because you can't join these collections together to query them at the same time. Well, at least that was the case until now. Firebase just recently released a new feature called Collection Group Queries. In today's video you'll learn how this new feature makes working with sub a lot more intuitive.

And we'll put this new feature to use to make a deeply nested threaded comments feature with Angular. If you're new here, like and subscribe, and you can grab the Source code from FireShip IO. And if you're building a product with Firestore, consider becoming a pro member to get access to the data modeling course. Let's first take a look at the problem that we can now solve with a Collection group query. Let's consider the very typical data model of blog post comments.

Users can have many comments, posts can have many comments, and a comment belongs to a post and a user. We'll have at least 2 screens in the app that we want to fill with data. Most commonly, we'll want to show all of the comments associated to a given post, But we might also have something like a user activity feed that queries all the most recent comments from that user. Reddit would be a perfect example of this. And Reddit also allows users to respond to comments so you can get these deeply nested threads of comments, which is another problem that is much easier to solve with collection group queries.

Now if you've been using Firestore for a while, the most likely way that you've modeled a relationship like this was to create a root collection of comments and then save a Post ID as well as a user ID on each individual comment. The reason you wouldn't make comments a sub collection of a post is because you then wouldn't be able to query all of the comments created by an individual user. And that's the exact problem that collection group solves because it allows you to group all the collections in the database based on a shared name or ID. And it doesn't matter how deeply nested these collections are, they can be nested up to a 100 levels deep and still be included in a collection group query. And that's extremely useful when you have a complex hierarchy of data like you would with Reddit comments.

In this example here, we have a collection of posts And then you can see an individual demo post has a sub collection of comments. The comment document itself has a user ID and the comment text. Now in order to create a Reddit style hierarchy, we can also give each individual comment its own sub collection of comments. The only important part for the query is that the sub collection shares the same name, we can just continue to follow this pattern until we hit Firestore's limit of 100 nested subcollections. So this data model preserves the hierarchy of comments and replies, but now let's take a look at how we can group these collections together to query them based on the user ID and also some of the caveats that you'll run into along the way.

First, let's take a look at some vanilla JavaScript using the Firebase SDK version 6 point o or greater. To join all of these subcollections together, we just call database collection group with the name of the collections, which in this case is comments. That's going to find all of the comments collections throughout the entire database and join them together, and then we can make queries across them just like we would with a normal collection. For example, we can call where the user equals a certain user ID to filter just by that user, Or we might want to order by a created at timestamp. But if you try to actually run this query in your own code, the first thing you'll see is this Firebase error missing or insufficient permissions.

That's because there are some special rules in place for collection group queries. First of all, at the very top of my rules, you'll notice that I'm enabling the rules version 2. In this example, we just wanna go ahead and make all of the comments readable and writable. So we'll say path equals star star slash comments, And that will allow access to any document in a comment sub collection. But in a real app, you would most likely lock down right access for the logged in user with a matching user ID.

So that's going to take care of the permission error, but now we're going to see an error that says that we need an index for this query. That will also give you a link directly to the Firebase console to create the index, So go ahead and click on that. Unlike a regular collection query, you'll need an index for every collection group that is filtered by a certain property. That'll take a minute or 2 to set up, but once it's done, you should be able to make this query successfully. Now that you know how collection group queries work, I want to show you how you can actually make use of these deeply tested data structures in a real world JavaScript application.

We'll be using Angular, and at the time of this video, you'll need to install AngularFire using the next tag. And what we're building is just the front end application that can query the data that I showed you earlier in the data model. First, we query the top level sub collection associated with the post. Then from there, the user can lazily load additional comments or replies to an individual comment by clicking this more button. And another nice thing about this data model is that we can query the data very efficiently and as we'll see, we can do so in a way that doesn't require any complex query code.

And we'll also create a second view that uses the collection group query to flatten all of this data out for a single user. The first thing we'll do is go into this post component, which is responsible for displaying the post itself as well as the sub collection of comments nested under it. Now to get the first level of comments that are nested under a post, All we have to do is make a reference to that subcollection in the database, and then we'll make sure to call snapshot changes here as opposed to value changes. And the reason we call snapshot changes here is because it contains additional data about the document itself like the ID, but more importantly, the full path to the document in the database. Now in the component HTML, we can go ahead and loop over that observable of snapshots, and then we'll pass each individual snapshot into this app comment component, which we'll create in the step.

Setting up an NG 4 loop with the async pipe will automatically subscribe to that observable to retrieve the items from the database, then we'll handle all the presentation logic in this child comment component. In the comment component, the first thing we'll do is set up the input property so we can pass the document snapshot from the parent to the Tiled. The query document snapshot contains all the data from that document in the database, but it also contains the document ID and the full path to that document in the database. But each individual comment might also contain its own subcollection of comments, which we'll go ahead and call replies here as the property on this component. Now we can come down here to n g on init to define all these properties.

The ID and the data just live directly on the document snapshot. We can get the full path to the document as a string by calling comment ref path. We need this full path to make a reference to the sub collection. We can make that reference by calling database collection, then passing in the path and appending comments to the end of it. That'll give us a reference to the sub collection of comments nested under this particular comment, Then we can use snapshot changes to get the actual data snapshots as an observable.

Now the last thing I'll do is add a method down here that allows the user to flip the show property to true And that will be fired when the user clicks the show replies button. In the template, I'm gonna go ahead and show the full path to the document in the database as well as the actual text of the comment. Then I'm going to set up a div here with n g f, so this will not be rendered unless that show property is true. And then inside that div, I'm going to add the app comment template, which is the same template that we're defining right now, so we're calling it recursively. And this works really well because the observable won't be created or subscribed to until the show property equals true.

That gives us a very easy way to lazy load data on a deeply nested thread. Now if you wanted to traverse the entire tree of comments by default, all you would have to do is set the show property to true and it would fetch every single comment nested under the starting point. And that's all it takes to access deeply nested data like this, so using a recursive pattern like can be very powerful and very simple at the same time. And the great thing about a collection group query is that it's now practical to do this because we can also make additional queries Cross this data without having to worry about it being deeply nested. And that actually becomes the easiest part of all because all we have to do now is go into our user comments component, then we call a database collection group, Point to the comments collection name and then just call snapshot changes with whatever query logic that we want to apply there.

And that will give us all the comments for that user, but without Out the hierarchy structure, so we get them flattened out in just a regular array that we can loop over. Overall, the collection group query is a very simple feature, but one that Adds a ton of flexibility to data modeling in Firestore. I wouldn't recommend going and restructuring your existing database, but it is definitely a feature you should consider going forward. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a Pro Member at Fireship IO.

You'll get access to the full Firestore Data Modeling course as well as a bunch of other exclusive content. Thanks for watching and I will talk to you soon.
1 of the most frustrating things about Firestore is modeling your data as a hierarchy of subcollections, because even though this is a very intuitive data model that represents relationships very well. It's not very practical because you can't join these collections together to query them at the same time.
databases
Well, at least that was the case until now. Firebase just recently released a new feature called Collection Group Queries. In today's video you'll learn how this new feature makes working with sub a lot more intuitive.
And we'll put this new feature to use to make a deeply nested threaded comments feature with Angular. If you're new here, like and subscribe, and you can grab the Source code from FireShip IO. And if you're building a product with Firestore, consider becoming a pro member to get access to the data modeling course. Let's first take a look at the problem that we can now solve with a Collection group query. Let's consider the very typical data model of blog post comments. Users can have many comments, posts can have many comments, and a comment belongs to a post and a user. We'll have at least 2 screens in the app that we want to fill with data. Most commonly, we'll want to show all of the comments associated to a given post, But we might also have something like a user activity feed that queries all the most recent comments from that user.
blogging
data management
databases
Reddit would be a perfect example of this. And Reddit also allows users to respond to comments so you can get these deeply nested threads of comments, which is another problem that is much easier to solve with collection group queries.
Now if you've been using Firestore for a while, the most likely way that you've modeled a relationship like this was to create a root collection of comments and then save a Post ID as well as a user ID on each individual comment. The reason you wouldn't make comments a sub collection of a post is because you then wouldn't be able to query all of the comments created by an individual user.
blogging
And that's the exact problem that collection group solves because it allows you to group all the collections in the database based on a shared name or ID. And it doesn't matter how deeply nested these collections are, they can be nested up to a 100 levels deep and still be included in a collection group query. And that's extremely useful when you have a complex hierarchy of data like you would with Reddit comments. In this example here, we have a collection of posts And then you can see an individual demo post has a sub collection of comments.
databases
The comment document itself has a user ID and the comment text. Now in order to create a Reddit style hierarchy, we can also give each individual comment its own sub collection of comments.
The only important part for the query is that the sub collection shares the same name, we can just continue to follow this pattern until we hit Firestore's limit of 100 nested subcollections. So this data model preserves the hierarchy of comments and replies, but now let's take a look at how we can group these collections together to query them based on the user ID and also some of the caveats that you'll run into along the way. First, let's take a look at some vanilla JavaScript using the Firebase SDK version 6 point o or greater. To join all of these subcollections together, we just call database collection group with the name of the collections, which in this case is comments. That's going to find all of the comments collections throughout the entire database and join them together, and then we can make queries across them just like we would with a normal collection. For example, we can call where the user equals a certain user ID to filter just by that user, Or we might want to order by a created at timestamp.
databases
data
But if you try to actually run this query in your own code, the first thing you'll see is this Firebase error missing or insufficient permissions. That's because there are some special rules in place for collection group queries. First of all, at the very top of my rules, you'll notice that I'm enabling the rules version 2. In this example, we just wanna go ahead and make all of the comments readable and writable. So we'll say path equals star star slash comments, And that will allow access to any document in a comment sub collection. But in a real app, you would most likely lock down right access for the logged in user with a matching user ID. So that's going to take care of the permission error, but now we're going to see an error that says that we need an index for this query. That will also give you a link directly to the Firebase console to create the index, So go ahead and click on that. Unlike a regular collection query, you'll need an index for every collection group that is filtered by a certain property.
That'll take a minute or 2 to set up, but once it's done, you should be able to make this query successfully. Now that you know how collection group queries work, I want to show you how you can actually make use of these deeply tested data structures in a real world JavaScript application.
databases
We'll be using Angular, and at the time of this video, you'll need to install AngularFire using the next tag. And what we're building is just the front end application that can query the data that I showed you earlier in the data model. First, we query the top level sub collection associated with the post. Then from there, the user can lazily load additional comments or replies to an individual comment by clicking this more button.
And another nice thing about this data model is that we can query the data very efficiently and as we'll see, we can do so in a way that doesn't require any complex query code. And we'll also create a second view that uses the collection group query to flatten all of this data out for a single user. The first thing we'll do is go into this post component, which is responsible for displaying the post itself as well as the sub collection of comments nested under it. Now to get the first level of comments that are nested under a post, All we have to do is make a reference to that subcollection in the database, and then we'll make sure to call snapshot changes here as opposed to value changes. And the reason we call snapshot changes here is because it contains additional data about the document itself like the ID, but more importantly, the full path to the document in the database. Now in the component HTML, we can go ahead and loop over that observable of snapshots, and then we'll pass each individual snapshot into this app comment component, which we'll create in the step.
data management
data
data analysis
databases
photography
Setting up an NG 4 loop with the async pipe will automatically subscribe to that observable to retrieve the items from the database, then we'll handle all the presentation logic in this child comment component.
In the comment component, the first thing we'll do is set up the input property so we can pass the document snapshot from the parent to the Tiled. The query document snapshot contains all the data from that document in the database, but it also contains the document ID and the full path to that document in the database. But each individual comment might also contain its own subcollection of comments, which we'll go ahead and call replies here as the property on this component. Now we can come down here to n g on init to define all these properties. The ID and the data just live directly on the document snapshot.
databases
documentation
We can get the full path to the document as a string by calling comment ref path. We need this full path to make a reference to the sub collection.
We can make that reference by calling database collection, then passing in the path and appending comments to the end of it. That'll give us a reference to the sub collection of comments nested under this particular comment, Then we can use snapshot changes to get the actual data snapshots as an observable.
databases
Now the last thing I'll do is add a method down here that allows the user to flip the show property to true And that will be fired when the user clicks the show replies button. In the template, I'm gonna go ahead and show the full path to the document in the database as well as the actual text of the comment. Then I'm going to set up a div here with n g f, so this will not be rendered unless that show property is true.
And then inside that div, I'm going to add the app comment template, which is the same template that we're defining right now, so we're calling it recursively. And this works really well because the observable won't be created or subscribed to until the show property equals true. That gives us a very easy way to lazy load data on a deeply nested thread.
programming
Now if you wanted to traverse the entire tree of comments by default, all you would have to do is set the show property to true and it would fetch every single comment nested under the starting point.
And that's all it takes to access deeply nested data like this, so using a recursive pattern like can be very powerful and very simple at the same time. And the great thing about a collection group query is that it's now practical to do this because we can also make additional queries Cross this data without having to worry about it being deeply nested. And that actually becomes the easiest part of all because all we have to do now is go into our user comments component, then we call a database collection group, Point to the comments collection name and then just call snapshot changes with whatever query logic that we want to apply there. And that will give us all the comments for that user, but without Out the hierarchy structure, so we get them flattened out in just a regular array that we can loop over. Overall, the collection group query is a very simple feature, but one that Adds a ton of flexibility to data modeling in Firestore. I wouldn't recommend going and restructuring your existing database, but it is definitely a feature you should consider going forward. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a Pro Member at Fireship IO. You'll get access to the full Firestore Data Modeling course as well as a bunch of other exclusive content. Thanks for watching and I will talk to you soon.
databases
streaming
data management
websites
commerce
data
customer support
1 of the most frustrating things about Firestore is modeling your data as a hierarchy of subcollections, because even though this is a very intuitive data model that represents relationships very well. It's not very practical because you can't join these collections together to query them at the same time. Well, at least that was the case until now. Firebase just recently released a new feature called Collection Group Queries. In today's video you'll learn how this new feature makes working with sub a lot more intuitive. And we'll put this new feature to use to make a deeply nested threaded comments feature with Angular. If you're new here, like and subscribe, and you can grab the Source code from FireShip IO. And if you're building a product with Firestore, consider becoming a pro member to get access to the data modeling course. Let's first take a look at the problem that we can now solve with a Collection group query. Let's consider the very typical data model of blog post comments. Users can have many comments, posts can have many comments, and a comment belongs to a post and a user. We'll have at least 2 screens in the app that we want to fill with data. Most commonly, we'll want to show all of the comments associated to a given post, But we might also have something like a user activity feed that queries all the most recent comments from that user. Reddit would be a perfect example of this. And Reddit also allows users to respond to comments so you can get these deeply nested threads of comments, which is another problem that is much easier to solve with collection group queries. Now if you've been using Firestore for a while, the most likely way that you've modeled a relationship like this was to create a root collection of comments and then save a Post ID as well as a user ID on each individual comment. The reason you wouldn't make comments a sub collection of a post is because you then wouldn't be able to query all of the comments created by an individual user. And that's the exact problem that collection group solves because it allows you to group all the collections in the database based on a shared name or ID. And it doesn't matter how deeply nested these collections are, they can be nested up to a 100 levels deep and still be included in a collection group query. And that's extremely useful when you have a complex hierarchy of data like you would with Reddit comments. In this example here, we have a collection of posts And then you can see an individual demo post has a sub collection of comments. The comment document itself has a user ID and the comment text. Now in order to create a Reddit style hierarchy, we can also give each individual comment its own sub collection of comments. The only important part for the query is that the sub collection shares the same name, we can just continue to follow this pattern until we hit Firestore's limit of 100 nested subcollections. So this data model preserves the hierarchy of comments and replies, but now let's take a look at how we can group these collections together to query them based on the user ID and also some of the caveats that you'll run into along the way. First, let's take a look at some vanilla JavaScript using the Firebase SDK version 6 point o or greater. To join all of these subcollections together, we just call database collection group with the name of the collections, which in this case is comments. That's going to find all of the comments collections throughout the entire database and join them together, and then we can make queries across them just like we would with a normal collection. For example, we can call where the user equals a certain user ID to filter just by that user, Or we might want to order by a created at timestamp. But if you try to actually run this query in your own code, the first thing you'll see is this Firebase error missing or insufficient permissions. That's because there are some special rules in place for collection group queries. First of all, at the very top of my rules, you'll notice that I'm enabling the rules version 2. In this example, we just wanna go ahead and make all of the comments readable and writable. So we'll say path equals star star slash comments, And that will allow access to any document in a comment sub collection. But in a real app, you would most likely lock down right access for the logged in user with a matching user ID. So that's going to take care of the permission error, but now we're going to see an error that says that we need an index for this query. That will also give you a link directly to the Firebase console to create the index, So go ahead and click on that. Unlike a regular collection query, you'll need an index for every collection group that is filtered by a certain property. That'll take a minute or 2 to set up, but once it's done, you should be able to make this query successfully. Now that you know how collection group queries work, I want to show you how you can actually make use of these deeply tested data structures in a real world JavaScript application. We'll be using Angular, and at the time of this video, you'll need to install AngularFire using the next tag. And what we're building is just the front end application that can query the data that I showed you earlier in the data model. First, we query the top level sub collection associated with the post. Then from there, the user can lazily load additional comments or replies to an individual comment by clicking this more button. And another nice thing about this data model is that we can query the data very efficiently and as we'll see, we can do so in a way that doesn't require any complex query code. And we'll also create a second view that uses the collection group query to flatten all of this data out for a single user. The first thing we'll do is go into this post component, which is responsible for displaying the post itself as well as the sub collection of comments nested under it. Now to get the first level of comments that are nested under a post, All we have to do is make a reference to that subcollection in the database, and then we'll make sure to call snapshot changes here as opposed to value changes. And the reason we call snapshot changes here is because it contains additional data about the document itself like the ID, but more importantly, the full path to the document in the database. Now in the component HTML, we can go ahead and loop over that observable of snapshots, and then we'll pass each individual snapshot into this app comment component, which we'll create in the step. Setting up an NG 4 loop with the async pipe will automatically subscribe to that observable to retrieve the items from the database, then we'll handle all the presentation logic in this child comment component. In the comment component, the first thing we'll do is set up the input property so we can pass the document snapshot from the parent to the Tiled. The query document snapshot contains all the data from that document in the database, but it also contains the document ID and the full path to that document in the database. But each individual comment might also contain its own subcollection of comments, which we'll go ahead and call replies here as the property on this component. Now we can come down here to n g on init to define all these properties. The ID and the data just live directly on the document snapshot. We can get the full path to the document as a string by calling comment ref path. We need this full path to make a reference to the sub collection. We can make that reference by calling database collection, then passing in the path and appending comments to the end of it. That'll give us a reference to the sub collection of comments nested under this particular comment, Then we can use snapshot changes to get the actual data snapshots as an observable. Now the last thing I'll do is add a method down here that allows the user to flip the show property to true And that will be fired when the user clicks the show replies button. In the template, I'm gonna go ahead and show the full path to the document in the database as well as the actual text of the comment. Then I'm going to set up a div here with n g f, so this will not be rendered unless that show property is true. And then inside that div, I'm going to add the app comment template, which is the same template that we're defining right now, so we're calling it recursively. And this works really well because the observable won't be created or subscribed to until the show property equals true. That gives us a very easy way to lazy load data on a deeply nested thread. Now if you wanted to traverse the entire tree of comments by default, all you would have to do is set the show property to true and it would fetch every single comment nested under the starting point. And that's all it takes to access deeply nested data like this, so using a recursive pattern like can be very powerful and very simple at the same time. And the great thing about a collection group query is that it's now practical to do this because we can also make additional queries Cross this data without having to worry about it being deeply nested. And that actually becomes the easiest part of all because all we have to do now is go into our user comments component, then we call a database collection group, Point to the comments collection name and then just call snapshot changes with whatever query logic that we want to apply there. And that will give us all the comments for that user, but without Out the hierarchy structure, so we get them flattened out in just a regular array that we can loop over. Overall, the collection group query is a very simple feature, but one that Adds a ton of flexibility to data modeling in Firestore. I wouldn't recommend going and restructuring your existing database, but it is definitely a feature you should consider going forward. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a Pro Member at Fireship IO. You'll get access to the full Firestore Data Modeling course as well as a bunch of other exclusive content. Thanks for watching and I will talk to you soon.
1
1
of
of
the
the
most
most
frustrating
frustrating
things
things
about
about
Firestore
firestore
is
is
modeling
modeling
your
your
data
data
as
as
a
a
hierarchy
hierarchy
of
of
subcollections,
subcollections
because
because
even
even
though
though
this
this
is
is
a
a
very
very
intuitive
intuitive
data
data
model
model
that
that
represents
represents
relationships
relationships
very
very
well.
well
It's
it's
not
not
very
very
practical
practical
because
because
you
you
can't
can't
join
join
these
these
collections
collections
together
together
to
to
query
query
them
them
at
at
the
the
same
same
time.
time
Well,
well
at
at
least
least
that
that
was
was
the
the
case
case
until
until
now.
now
Firebase
firebase
just
just
recently
recently
released
released
a
a
new
new
feature
feature
called
called
Collection
collection
Group
group
Queries.
queries
In
in
today's
today's
video
video
you'll
you'll
learn
learn
how
how
this
this
new
new
feature
feature
makes
makes
working
working
with
with
sub
sub
a
a
lot
lot
more
more
intuitive.
intuitive
And
and
we'll
we'll
put
put
this
this
new
new
feature
feature
to
to
use
use
to
to
make
make
a
a
deeply
deeply
nested
nested
threaded
threaded
comments
comments
feature
feature
with
with
Angular.
angular
If
if
you're
you're
new
new
here,
here
like
like
and
and
subscribe,
subscribe
and
and
you
you
can
can
grab
grab
the
the
Source
source
code
code
from
from
FireShip
fireship
IO.
io
And
and
if
if
you're
you're
building
building
a
a
product
product
with
with
Firestore,
firestore
consider
consider
becoming
becoming
a
a
pro
pro
member
member
to
to
get
get
access
access
to
to
the
the
data
data
modeling
modeling
course.
course
Let's
let's
first
first
take
take
a
a
look
look
at
at
the
the
problem
problem
that
that
we
we
can
can
now
now
solve
solve
with
with
a
a
Collection
collection
group
group
query.
query
Let's
let's
consider
consider
the
the
very
very
typical
typical
data
data
model
model
of
of
blog
blog
post
post
comments.
comments
Users
users
can
can
have
have
many
many
comments,
comments
posts
posts
can
can
have
have
many
many
comments,
comments
and
and
a
a
comment
comment
belongs
belongs
to
to
a
a
post
post
and
and
a
a
user.
user
We'll
we'll
have
have
at
at
least
least
2
2
screens
screens
in
in
the
the
app
app
that
that
we
we
want
want
to
to
fill
fill
with
with
data.
data
Most
most
commonly,
commonly
we'll
we'll
want
want
to
to
show
show
all
all
of
of
the
the
comments
comments
associated
associated
to
to
a
a
given
given
post,
post
But
but
we
we
might
might
also
also
have
have
something
something
like
like
a
a
user
user
activity
activity
feed
feed
that
that
queries
queries
all
all
the
the
most
most
recent
recent
comments
comments
from
from
that
that
user.
user
Reddit
reddit
would
would
be
be
a
a
perfect
perfect
example
example
of
of
this.
this
And
and
Reddit
reddit
also
also
allows
allows
users
users
to
to
respond
respond
to
to
comments
comments
so
so
you
you
can
can
get
get
these
these
deeply
deeply
nested
nested
threads
threads
of
of
comments,
comments
which
which
is
is
another
another
problem
problem
that
that
is
is
much
much
easier
easier
to
to
solve
solve
with
with
collection
collection
group
group
queries.
queries
Now
now
if
if
you've
you've
been
been
using
using
Firestore
firestore
for
for
a
a
while,
while
the
the
most
most
likely
likely
way
way
that
that
you've
you've
modeled
modeled
a
a
relationship
relationship
like
like
this
this
was
was
to
to
create
create
a
a
root
root
collection
collection
of
of
comments
comments
and
and
then
then
save
save
a
a
Post
post
ID
id
as
as
well
well
as
as
a
a
user
user
ID
id
on
on
each
each
individual
individual
comment.
comment
The
the
reason
reason
you
you
wouldn't
wouldn't
make
make
comments
comments
a
a
sub
sub
collection
collection
of
of
a
a
post
post
is
is
because
because
you
you
then
then
wouldn't
wouldn't
be
be
able
able
to
to
query
query
all
all
of
of
the
the
comments
comments
created
created
by
by
an
an
individual
individual
user.
user
And
and
that's
that's
the
the
exact
exact
problem
problem
that
that
collection
collection
group
group
solves
solves
because
because
it
it
allows
allows
you
you
to
to
group
group
all
all
the
the
collections
collections
in
in
the
the
database
database
based
based
on
on
a
a
shared
shared
name
name
or
or
ID.
id
And
and
it
it
doesn't
doesn't
matter
matter
how
how
deeply
deeply
nested
nested
these
these
collections
collections
are,
are
they
they
can
can
be
be
nested
nested
up
up
to
to
a
a
100
100
levels
levels
deep
deep
and
and
still
still
be
be
included
included
in
in
a
a
collection
collection
group
group
query.
query
And
and
that's
that's
extremely
extremely
useful
useful
when
when
you
you
have
have
a
a
complex
complex
hierarchy
hierarchy
of
of
data
data
like
like
you
you
would
would
with
with
Reddit
reddit
comments.
comments
In
in
this
this
example
example
here,
here
we
we
have
have
a
a
collection
collection
of
of
posts
posts
And
and
then
then
you
you
can
can
see
see
an
an
individual
individual
demo
demo
post
post
has
has
a
a
sub
sub
collection
collection
of
of
comments.
comments
The
the
comment
comment
document
document
itself
itself
has
has
a
a
user
user
ID
id
and
and
the
the
comment
comment
text.
text
Now
now
in
in
order
order
to
to
create
create
a
a
Reddit
reddit
style
style
hierarchy,
hierarchy
we
we
can
can
also
also
give
give
each
each
individual
individual
comment
comment
its
its
own
own
sub
sub
collection
collection
of
of
comments.
comments
The
the
only
only
important
important
part
part
for
for
the
the
query
query
is
is
that
that
the
the
sub
sub
collection
collection
shares
shares
the
the
same
same
name,
name
we
we
can
can
just
just
continue
continue
to
to
follow
follow
this
this
pattern
pattern
until
until
we
we
hit
hit
Firestore's
firestore's
limit
limit
of
of
100
100
nested
nested
subcollections.
subcollections
So
so
this
this
data
data
model
model
preserves
preserves
the
the
hierarchy
hierarchy
of
of
comments
comments
and
and
replies,
replies
but
but
now
now
let's
let's
take
take
a
a
look
look
at
at
how
how
we
we
can
can
group
group
these
these
collections
collections
together
together
to
to
query
query
them
them
based
based
on
on
the
the
user
user
ID
id
and
and
also
also
some
some
of
of
the
the
caveats
caveats
that
that
you'll
you'll
run
run
into
into
along
along
the
the
way.
way
First,
first
let's
let's
take
take
a
a
look
look
at
at
some
some
vanilla
vanilla
JavaScript
javascript
using
using
the
the
Firebase
firebase
SDK
sdk
version
version
6
6
point
point
o
o
or
or
greater.
greater
To
to
join
join
all
all
of
of
these
these
subcollections
subcollections
together,
together
we
we
just
just
call
call
database
database
collection
collection
group
group
with
with
the
the
name
name
of
of
the
the
collections,
collections
which
which
in
in
this
this
case
case
is
is
comments.
comments
That's
that's
going
going
to
to
find
find
all
all
of
of
the
the
comments
comments
collections
collections
throughout
throughout
the
the
entire
entire
database
database
and
and
join
join
them
them
together,
together
and
and
then
then
we
we
can
can
make
make
queries
queries
across
across
them
them
just
just
like
like
we
we
would
would
with
with
a
a
normal
normal
collection.
collection
For
for
example,
example
we
we
can
can
call
call
where
where
the
the
user
user
equals
equals
a
a
certain
certain
user
user
ID
id
to
to
filter
filter
just
just
by
by
that
that
user,
user
Or
or
we
we
might
might
want
want
to
to
order
order
by
by
a
a
created
created
at
at
timestamp.
timestamp
But
but
if
if
you
you
try
try
to
to
actually
actually
run
run
this
this
query
query
in
in
your
your
own
own
code,
code
the
the
first
first
thing
thing
you'll
you'll
see
see
is
is
this
this
Firebase
firebase
error
error
missing
missing
or
or
insufficient
insufficient
permissions.
permissions
That's
that's
because
because
there
there
are
are
some
some
special
special
rules
rules
in
in
place
place
for
for
collection
collection
group
group
queries.
queries
First
first
of
of
all,
all
at
at
the
the
very
very
top
top
of
of
my
my
rules,
rules
you'll
you'll
notice
notice
that
that
I'm
i'm
enabling
enabling
the
the
rules
rules
version
version
2.
2
In
in
this
this
example,
example
we
we
just
just
wanna
wanna
go
go
ahead
ahead
and
and
make
make
all
all
of
of
the
the
comments
comments
readable
readable
and
and
writable.
writable
So
so
we'll
we'll
say
say
path
path
equals
equals
star
star
star
star
slash
slash
comments,
comments
And
and
that
that
will
will
allow
allow
access
access
to
to
any
any
document
document
in
in
a
a
comment
comment
sub
sub
collection.
collection
But
but
in
in
a
a
real
real
app,
app
you
you
would
would
most
most
likely
likely
lock
lock
down
down
right
right
access
access
for
for
the
the
logged
logged
in
in
user
user
with
with
a
a
matching
matching
user
user
ID.
id
So
so
that's
that's
going
going
to
to
take
take
care
care
of
of
the
the
permission
permission
error,
error
but
but
now
now
we're
we're
going
going
to
to
see
see
an
an
error
error
that
that
says
says
that
that
we
we
need
need
an
an
index
index
for
for
this
this
query.
query
That
that
will
will
also
also
give
give
you
you
a
a
link
link
directly
directly
to
to
the
the
Firebase
firebase
console
console
to
to
create
create
the
the
index,
index
So
so
go
go
ahead
ahead
and
and
click
click
on
on
that.
that
Unlike
unlike
a
a
regular
regular
collection
collection
query,
query
you'll
you'll
need
need
an
an
index
index
for
for
every
every
collection
collection
group
group
that
that
is
is
filtered
filtered
by
by
a
a
certain
certain
property.
property
That'll
that'll
take
take
a
a
minute
minute
or
or
2
2
to
to
set
set
up,
up
but
but
once
once
it's
it's
done,
done
you
you
should
should
be
be
able
able
to
to
make
make
this
this
query
query
successfully.
successfully
Now
now
that
that
you
you
know
know
how
how
collection
collection
group
group
queries
queries
work,
work
I
i
want
want
to
to
show
show
you
you
how
how
you
you
can
can
actually
actually
make
make
use
use
of
of
these
these
deeply
deeply
tested
tested
data
data
structures
structures
in
in
a
a
real
real
world
world
JavaScript
javascript
application.
application
We'll
we'll
be
be
using
using
Angular,
angular
and
and
at
at
the
the
time
time
of
of
this
this
video,
video
you'll
you'll
need
need
to
to
install
install
AngularFire
angularfire
using
using
the
the
next
next
tag.
tag
And
and
what
what
we're
we're
building
building
is
is
just
just
the
the
front
front
end
end
application
application
that
that
can
can
query
query
the
the
data
data
that
that
I
i
showed
showed
you
you
earlier
earlier
in
in
the
the
data
data
model.
model
First,
first
we
we
query
query
the
the
top
top
level
level
sub
sub
collection
collection
associated
associated
with
with
the
the
post.
post
Then
then
from
from
there,
there
the
the
user
user
can
can
lazily
lazily
load
load
additional
additional
comments
comments
or
or
replies
replies
to
to
an
an
individual
individual
comment
comment
by
by
clicking
clicking
this
this
more
more
button.
button
And
and
another
another
nice
nice
thing
thing
about
about
this
this
data
data
model
model
is
is
that
that
we
we
can
can
query
query
the
the
data
data
very
very
efficiently
efficiently
and
and
as
as
we'll
we'll
see,
see
we
we
can
can
do
do
so
so
in
in
a
a
way
way
that
that
doesn't
doesn't
require
require
any
any
complex
complex
query
query
code.
code
And
and
we'll
we'll
also
also
create
create
a
a
second
second
view
view
that
that
uses
uses
the
the
collection
collection
group
group
query
query
to
to
flatten
flatten
all
all
of
of
this
this
data
data
out
out
for
for
a
a
single
single
user.
user
The
the
first
first
thing
thing
we'll
we'll
do
do
is
is
go
go
into
into
this
this
post
post
component,
component
which
which
is
is
responsible
responsible
for
for
displaying
displaying
the
the
post
post
itself
itself
as
as
well
well
as
as
the
the
sub
sub
collection
collection
of
of
comments
comments
nested
nested
under
under
it.
it
Now
now
to
to
get
get
the
the
first
first
level
level
of
of
comments
comments
that
that
are
are
nested
nested
under
under
a
a
post,
post
All
all
we
we
have
have
to
to
do
do
is
is
make
make
a
a
reference
reference
to
to
that
that
subcollection
subcollection
in
in
the
the
database,
database
and
and
then
then
we'll
we'll
make
make
sure
sure
to
to
call
call
snapshot
snapshot
changes
changes
here
here
as
as
opposed
opposed
to
to
value
value
changes.
changes
And
and
the
the
reason
reason
we
we
call
call
snapshot
snapshot
changes
changes
here
here
is
is
because
because
it
it
contains
contains
additional
additional
data
data
about
about
the
the
document
document
itself
itself
like
like
the
the
ID,
id
but
but
more
more
importantly,
importantly
the
the
full
full
path
path
to
to
the
the
document
document
in
in
the
the
database.
database
Now
now
in
in
the
the
component
component
HTML,
html
we
we
can
can
go
go
ahead
ahead
and
and
loop
loop
over
over
that
that
observable
observable
of
of
snapshots,
snapshots
and
and
then
then
we'll
we'll
pass
pass
each
each
individual
individual
snapshot
snapshot
into
into
this
this
app
app
comment
comment
component,
component
which
which
we'll
we'll
create
create
in
in
the
the
step.
step
Setting
setting
up
up
an
an
NG
ng
4
4
loop
loop
with
with
the
the
async
async
pipe
pipe
will
will
automatically
automatically
subscribe
subscribe
to
to
that
that
observable
observable
to
to
retrieve
retrieve
the
the
items
items
from
from
the
the
database,
database
then
then
we'll
we'll
handle
handle
all
all
the
the
presentation
presentation
logic
logic
in
in
this
this
child
child
comment
comment
component.
component
In
in
the
the
comment
comment
component,
component
the
the
first
first
thing
thing
we'll
we'll
do
do
is
is
set
set
up
up
the
the
input
input
property
property
so
so
we
we
can
can
pass
pass
the
the
document
document
snapshot
snapshot
from
from
the
the
parent
parent
to
to
the
the
Tiled.
tiled
The
the
query
query
document
document
snapshot
snapshot
contains
contains
all
all
the
the
data
data
from
from
that
that
document
document
in
in
the
the
database,
database
but
but
it
it
also
also
contains
contains
the
the
document
document
ID
id
and
and
the
the
full
full
path
path
to
to
that
that
document
document
in
in
the
the
database.
database
But
but
each
each
individual
individual
comment
comment
might
might
also
also
contain
contain
its
its
own
own
subcollection
subcollection
of
of
comments,
comments
which
which
we'll
we'll
go
go
ahead
ahead
and
and
call
call
replies
replies
here
here
as
as
the
the
property
property
on
on
this
this
component.
component
Now
now
we
we
can
can
come
come
down
down
here
here
to
to
n
n
g
g
on
on
init
init
to
to
define
define
all
all
these
these
properties.
properties
The
the
ID
id
and
and
the
the
data
data
just
just
live
live
directly
directly
on
on
the
the
document
document
snapshot.
snapshot
We
we
can
can
get
get
the
the
full
full
path
path
to
to
the
the
document
document
as
as
a
a
string
string
by
by
calling
calling
comment
comment
ref
ref
path.
path
We
we
need
need
this
this
full
full
path
path
to
to
make
make
a
a
reference
reference
to
to
the
the
sub
sub
collection.
collection
We
we
can
can
make
make
that
that
reference
reference
by
by
calling
calling
database
database
collection,
collection
then
then
passing
passing
in
in
the
the
path
path
and
and
appending
appending
comments
comments
to
to
the
the
end
end
of
of
it.
it
That'll
that'll
give
give
us
us
a
a
reference
reference
to
to
the
the
sub
sub
collection
collection
of
of
comments
comments
nested
nested
under
under
this
this
particular
particular
comment,
comment
Then
then
we
we
can
can
use
use
snapshot
snapshot
changes
changes
to
to
get
get
the
the
actual
actual
data
data
snapshots
snapshots
as
as
an
an
observable.
observable
Now
now
the
the
last
last
thing
thing
I'll
i'll
do
do
is
is
add
add
a
a
method
method
down
down
here
here
that
that
allows
allows
the
the
user
user
to
to
flip
flip
the
the
show
show
property
property
to
to
true
true
And
and
that
that
will
will
be
be
fired
fired
when
when
the
the
user
user
clicks
clicks
the
the
show
show
replies
replies
button.
button
In
in
the
the
template,
template
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
show
show
the
the
full
full
path
path
to
to
the
the
document
document
in
in
the
the
database
database
as
as
well
well
as
as
the
the
actual
actual
text
text
of
of
the
the
comment.
comment
Then
then
I'm
i'm
going
going
to
to
set
set
up
up
a
a
div
div
here
here
with
with
n
n
g
g
f,
f
so
so
this
this
will
will
not
not
be
be
rendered
rendered
unless
unless
that
that
show
show
property
property
is
is
true.
true
And
and
then
then
inside
inside
that
that
div,
div
I'm
i'm
going
going
to
to
add
add
the
the
app
app
comment
comment
template,
template
which
which
is
is
the
the
same
same
template
template
that
that
we're
we're
defining
defining
right
right
now,
now
so
so
we're
we're
calling
calling
it
it
recursively.
recursively
And
and
this
this
works
works
really
really
well
well
because
because
the
the
observable
observable
won't
won't
be
be
created
created
or
or
subscribed
subscribed
to
to
until
until
the
the
show
show
property
property
equals
equals
true.
true
That
that
gives
gives
us
us
a
a
very
very
easy
easy
way
way
to
to
lazy
lazy
load
load
data
data
on
on
a
a
deeply
deeply
nested
nested
thread.
thread
Now
now
if
if
you
you
wanted
wanted
to
to
traverse
traverse
the
the
entire
entire
tree
tree
of
of
comments
comments
by
by
default,
default
all
all
you
you
would
would
have
have
to
to
do
do
is
is
set
set
the
the
show
show
property
property
to
to
true
true
and
and
it
it
would
would
fetch
fetch
every
every
single
single
comment
comment
nested
nested
under
under
the
the
starting
starting
point.
point
And
and
that's
that's
all
all
it
it
takes
takes
to
to
access
access
deeply
deeply
nested
nested
data
data
like
like
this,
this
so
so
using
using
a
a
recursive
recursive
pattern
pattern
like
like
can
can
be
be
very
very
powerful
powerful
and
and
very
very
simple
simple
at
at
the
the
same
same
time.
time
And
and
the
the
great
great
thing
thing
about
about
a
a
collection
collection
group
group
query
query
is
is
that
that
it's
it's
now
now
practical
practical
to
to
do
do
this
this
because
because
we
we
can
can
also
also
make
make
additional
additional
queries
queries
Cross
cross
this
this
data
data
without
without
having
having
to
to
worry
worry
about
about
it
it
being
being
deeply
deeply
nested.
nested
And
and
that
that
actually
actually
becomes
becomes
the
the
easiest
easiest
part
part
of
of
all
all
because
because
all
all
we
we
have
have
to
to
do
do
now
now
is
is
go
go
into
into
our
our
user
user
comments
comments
component,
component
then
then
we
we
call
call
a
a
database
database
collection
collection
group,
group
Point
point
to
to
the
the
comments
comments
collection
collection
name
name
and
and
then
then
just
just
call
call
snapshot
snapshot
changes
changes
with
with
whatever
whatever
query
query
logic
logic
that
that
we
we
want
want
to
to
apply
apply
there.
there
And
and
that
that
will
will
give
give
us
us
all
all
the
the
comments
comments
for
for
that
that
user,
user
but
but
without
without
Out
out
the
the
hierarchy
hierarchy
structure,
structure
so
so
we
we
get
get
them
them
flattened
flattened
out
out
in
in
just
just
a
a
regular
regular
array
array
that
that
we
we
can
can
loop
loop
over.
over
Overall,
overall
the
the
collection
collection
group
group
query
query
is
is
a
a
very
very
simple
simple
feature,
feature
but
but
one
one
that
that
Adds
adds
a
a
ton
ton
of
of
flexibility
flexibility
to
to
data
data
modeling
modeling
in
in
Firestore.
firestore
I
i
wouldn't
wouldn't
recommend
recommend
going
going
and
and
restructuring
restructuring
your
your
existing
existing
database,
database
but
but
it
it
is
is
definitely
definitely
a
a
feature
feature
you
you
should
should
consider
consider
going
going
forward.
forward
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe
subscribe
and
and
consider
consider
becoming
becoming
a
a
Pro
pro
Member
member
at
at
Fireship
fireship
IO.
io
You'll
you'll
get
get
access
access
to
to
the
the
full
full
Firestore
firestore
Data
data
Modeling
modeling
course
course
as
as
well
well
as
as
a
a
bunch
bunch
of
of
other
other
exclusive
exclusive
content.
content
Thanks
thanks
for
for
watching
watching
and
and
I
i
will
will
talk
talk
to
to
you
you
soon.
soon
success
The speakers discuss the frustration of modeling data as sub reass and the new feature called Collection Grouphair. They explain how to create a root collection of comments and a user ID for each individual comment, and how to use the model to create a hierarchy of comments and user activity. They also recommend using a method to avoid deeply complicated queries and suggest setting up an NG 4 loop and app comment template. Finally, they recommend setting up an app comment template and offer a free course on Fir accuses.
Collection Group Queries in Firestore
1 of the most frustrating things about Firestore is modeling your data as a hierarchy of subcollections, because even though this is a very intuitive data model that represents relationships very well. It's not very practical because you can't join these collections together to query them at the same time. Well, at least that was the case until now. Firebase just recently released a new feature called Collection Group Queries. In today's video you'll learn how this new feature makes working with sub a lot more intuitive. And we'll put this new feature to use to make a deeply nested threaded comments feature with Angular. If you're new here, like and subscribe, and you can grab the Source code from FireShip IO. And if you're building a product with Firestore, consider becoming a pro member to get access to the data modeling course. Let's first take a look at the problem that we can now solve with a Collection group query. Let's consider the very typical data model of blog post comments. Users can have many comments, posts can have many comments, and a comment belongs to a post and a user. We'll have at least 2 screens in the app that we want to fill with data. Most commonly, we'll want to show all of the comments associated to a given post, But we might also have something like a user activity feed that queries all the most recent comments from that user. Reddit would be a perfect example of this. And Reddit also allows users to respond to comments so you can get these deeply nested threads of comments, which is another problem that is much easier to solve with collection group queries. Now if you've been using Firestore for a while, the most likely way that you've modeled a relationship like this was to create a root collection of comments and then save a Post ID as well as a user ID on each individual comment. The reason you wouldn't make comments a sub collection of a post is because you then wouldn't be able to query all of the comments created by an individual user. And that's the exact problem that collection group solves because it allows you to group all the collections in the database based on a shared name or ID. And it doesn't matter how deeply nested these collections are, they can be nested up to a 100 levels deep and still be included in a collection group query. And that's extremely useful when you have a complex hierarchy of data like you would with Reddit comments. In this example here, we have a collection of posts And then you can see an individual demo post has a sub collection of comments. The comment document itself has a user ID and the comment text. Now in order to create a Reddit style hierarchy, we can also give each individual comment its own sub collection of comments. The only important part for the query is that the sub collection shares the same name, we can just continue to follow this pattern until we hit Firestore's limit of 100 nested subcollections. So this data model preserves the hierarchy of comments and replies, but now let's take a look at how we can group these collections together to query them based on the user ID and also some of the caveats that you'll run into along the way. First, let's take a look at some vanilla JavaScript using the Firebase SDK version 6 point o or greater. To join all of these subcollections together, we just call database collection group with the name of the collections, which in this case is comments. That's going to find all of the comments collections throughout the entire database and join them together, and then we can make queries across them just like we would with a normal collection. For example, we can call where the user equals a certain user ID to filter just by that user, Or we might want to order by a created at timestamp. But if you try to actually run this query in your own code, the first thing you'll see is this Firebase error missing or insufficient permissions. That's because there are some special rules in place for collection group queries. First of all, at the very top of my rules, you'll notice that I'm enabling the rules version 2. In this example, we just wanna go ahead and make all of the comments readable and writable. So we'll say path equals star star slash comments, And that will allow access to any document in a comment sub collection. But in a real app, you would most likely lock down right access for the logged in user with a matching user ID. So that's going to take care of the permission error, but now we're going to see an error that says that we need an index for this query. That will also give you a link directly to the Firebase console to create the index, So go ahead and click on that. Unlike a regular collection query, you'll need an index for every collection group that is filtered by a certain property. That'll take a minute or 2 to set up, but once it's done, you should be able to make this query successfully. Now that you know how collection group queries work, I want to show you how you can actually make use of these deeply tested data structures in a real world JavaScript application. We'll be using Angular, and at the time of this video, you'll need to install AngularFire using the next tag. And what we're building is just the front end application that can query the data that I showed you earlier in the data model. First, we query the top level sub collection associated with the post. Then from there, the user can lazily load additional comments or replies to an individual comment by clicking this more button. And another nice thing about this data model is that we can query the data very efficiently and as we'll see, we can do so in a way that doesn't require any complex query code. And we'll also create a second view that uses the collection group query to flatten all of this data out for a single user. The first thing we'll do is go into this post component, which is responsible for displaying the post itself as well as the sub collection of comments nested under it. Now to get the first level of comments that are nested under a post, All we have to do is make a reference to that subcollection in the database, and then we'll make sure to call snapshot changes here as opposed to value changes. And the reason we call snapshot changes here is because it contains additional data about the document itself like the ID, but more importantly, the full path to the document in the database. Now in the component HTML, we can go ahead and loop over that observable of snapshots, and then we'll pass each individual snapshot into this app comment component, which we'll create in the step. Setting up an NG 4 loop with the async pipe will automatically subscribe to that observable to retrieve the items from the database, then we'll handle all the presentation logic in this child comment component. In the comment component, the first thing we'll do is set up the input property so we can pass the document snapshot from the parent to the Tiled. The query document snapshot contains all the data from that document in the database, but it also contains the document ID and the full path to that document in the database. But each individual comment might also contain its own subcollection of comments, which we'll go ahead and call replies here as the property on this component. Now we can come down here to n g on init to define all these properties. The ID and the data just live directly on the document snapshot. We can get the full path to the document as a string by calling comment ref path. We need this full path to make a reference to the sub collection. We can make that reference by calling database collection, then passing in the path and appending comments to the end of it. That'll give us a reference to the sub collection of comments nested under this particular comment, Then we can use snapshot changes to get the actual data snapshots as an observable. Now the last thing I'll do is add a method down here that allows the user to flip the show property to true And that will be fired when the user clicks the show replies button. In the template, I'm gonna go ahead and show the full path to the document in the database as well as the actual text of the comment. Then I'm going to set up a div here with n g f, so this will not be rendered unless that show property is true. And then inside that div, I'm going to add the app comment template, which is the same template that we're defining right now, so we're calling it recursively. And this works really well because the observable won't be created or subscribed to until the show property equals true. That gives us a very easy way to lazy load data on a deeply nested thread. Now if you wanted to traverse the entire tree of comments by default, all you would have to do is set the show property to true and it would fetch every single comment nested under the starting point. And that's all it takes to access deeply nested data like this, so using a recursive pattern like can be very powerful and very simple at the same time. And the great thing about a collection group query is that it's now practical to do this because we can also make additional queries Cross this data without having to worry about it being deeply nested. And that actually becomes the easiest part of all because all we have to do now is go into our user comments component, then we call a database collection group, Point to the comments collection name and then just call snapshot changes with whatever query logic that we want to apply there. And that will give us all the comments for that user, but without Out the hierarchy structure, so we get them flattened out in just a regular array that we can loop over. Overall, the collection group query is a very simple feature, but one that Adds a ton of flexibility to data modeling in Firestore. I wouldn't recommend going and restructuring your existing database, but it is definitely a feature you should consider going forward. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a Pro Member at Fireship IO. You'll get access to the full Firestore Data Modeling course as well as a bunch of other exclusive content. Thanks for watching and I will talk to you soon.
The speakers discuss the frustration of modeling data as sub reass and the new feature called Collection Grouphair. They explain how to create a root collection of comments and a user ID for each individual comment, and how to use the model to create a hierarchy of comments and user activity. They also recommend using a method to avoid deeply complicated queries and suggest setting up an NG 4 loop and app comment template. Finally, they recommend setting up an app comment template and offer a free course on Fir accuses.