I have a subcollection for each doc in the users collection of my app. This subcollection stores docs that are related to the user, however they could just as well be saved
Let's take an example for that. Let's assume we have a database schema for a quiz app that looks like this:
Firestore-root
|
--- questions (collections)
|
--- questionId (document)
|
--- questionId: "LongQuestionIdOne"
|
--- title: "Question Title"
|
--- tags (collections)
|
--- tagIdOne (document)
| |
| --- tagId: "yR8iLzdBdylFkSzg1k4K"
| |
| --- tagName: "History"
| |
| --- //Other tag properties
|
--- tagIdTwo (document)
|
--- tagId: "tUjKPoq2dylFkSzg9cFg"
|
--- tagName: "Geography"
|
--- //Other tag properties
In which tags
is a subcollection within questionId
object. Let's create now the tags
collection as a top-level collection like this:
Firestore-root
|
--- questions (collections)
| |
| --- questionId (document)
| |
| --- questionId: "LongQuestionIdOne"
| |
| --- title: "Question Title"
|
--- tags (collections)
|
--- tagIdOne (document)
| |
| --- tagId: "yR8iLzdBdylFkSzg1k4K"
| |
| --- tagName: "History"
| |
| --- questionId: "LongQuestionIdOne"
| |
| --- //Other tag properties
|
--- tagIdTwo (document)
|
--- tagId: "tUjKPoq2dylFkSzg9cFg"
|
--- tagName: "Geography"
|
--- questionId: "LongQuestionIdTwo"
|
--- //Other tag properties
The differences between this two approaches are:
tags
of a particular question, using the first schema it's very easy because only a CollectionReference
is needed (questions -> questionId -> tags). To achieve the same thing using the second schema, instead of a CollectionReference
, a Query
is needed, which means that you need to query the entire tags
collection to get only the tags that correspond to a single question.This technique is called database flatten and is a quite common practice when it comes to Firebase. So use this technique only if is needed. So in your case, if you only need to display the tags of a single question, use the first schema. If you want somehow to display all the tags of all questions, the second schema is recommended.
Is it solely there so that you can expand if your doc becomes close to the 1MB limit?
If you have a subcollection of objects within a document, please note that size of the subcollection it does not count in that 1 MiB limit. Only the data that is stored in the properties of the document is counted.
Edit Oct 01 2019:
According to @ShahoodulHassan comment:
So there is no way you can get all the tags of all the questions using the first schema?
Actually now there is, we can get all tags of all questions with the use of Firestore collection group query. One thing to note is that all the subcolletions must have the same name, for instance tags
.
The only potential technical advantage to sub-collections that I can think of relates to document size -- it allows you to omit a reference to the parent element. (i.e. for each related rootDocument -> subCollection
, there is a single pointer from the root collection document to the subcollection).
/messages
|
--> /messages/tags
When tags
are a sub-collection then they don't need to save the messageId
because you access the tags through message document:
collection("messages").document(messageId).collection("tags")
/messages
/tags
With a root tags
collection each tag would need to store messageId
. This basically flips the direction of the pointers.
collection("tags").whereEqualTo("messageId", messageId)
Sub-collection: pointers go from one -> many
Root collection: pointers go from many -> one