Reputation: 56
I have a document-based data structure filled with users. Information about the users will include a weekly agenda (activities to do in one week, ex: run 10 minutes on Monday, go shopping on Tuesday), and other essential information such as their first name, gender, age, etc.. Users can have multiple weekly agendas (for example, one for this week, another for the next week, etc..)
I do not know how to structure this data however.
Should there be two subdirectories inside the user directory, one named "weekly_agendas" (containing documents of all the user's weekly agendas), and another named "user_data," containing personal information such as name, gender, age, etc.. Essentially, nesting data is being created.
OR:
Should the "weekly_agendas" directory be moved outside of the users directory?
I have googled everywhere, and all documents typically suggest preventing nested data structure, but how could this nested data structure be bad?
This can help illustrate what I am trying to get at:
Structure #1
users
|
+--user_id
|
+--user_data
|
+--username
+--age
+--gender
+--weekly_agenda
|
+--weekly_agenda_number
|
+--1: walk the dog on Monday
+--2: Go shopping on Tuesday
Structure #2:
users
|
+--user_id
|
+--username
+--age
+--gender
+--weekly_agenda
|
+--user_id
|
+--weekly_agenda_number
|
+--1: walk the dog on Monday
+--2: Go shopping on Tuesday
Upvotes: 0
Views: 69
Reputation: 138814
There is no "perfect", "the best" or "the correct" solution for structuring a Cloud Firestore database.
I have googled everywhere, and all documents typically suggest preventing nested data structure, but how could this nested data structure be bad?
Unlike in Firebase real-time database where to display a list of weekly agendas, you would have been downloaded the entire user object, in Cloud Firestore this is not an issue anymore. So nesting a subcollection named weekly_agenda
under each user document won't be an issue. The down-side of the first approach is that you cannot query your database to display all agendas of all users. So a possible schema, that is a mix of your solution might be:
Firestore-root
|
--- users (collection)
| |
| --- uid (document)
| |
| --- username: "John"
| |
| --- age: 22
| |
| --- gender: "male"
|
--- weeklyAgenda (collection)
|
--- weeklyAgendaId (document)
|
--- uid: "UidOfTheUser"
|
--- //Weekly Agenda Properties
Using this schema you can simply:
users
collection.weeklyAgenda
collection.Query all agendas that belong to a single user by using a Query that in Android might look like this:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query query = productsRef.whereEqualTo("uid", uid);
This query can also be written in other programming languages.
Upvotes: 1
Reputation: 1120
(for future reference, this type of "best practice" question is better suited for the Firebase Google Group than Stack Overflow)
First, I'm not sure if this was intentional or a mistake in your diagram, but I just want to point out that in Structure #1, you should have username
, age
, and gender
as fields in the user document, not as a subcollection as the diagram suggests. (I'm guessing this is what you meant, given your description, but just to be sure, as the user data would be poor use of subcollections).
Now onto your main question:
Firestore benefits greatly when operating on a flat data structure, that is, one with a large quantity of small documents, as opposed to a small number of large documents. This is one of the points people refer to when talking about anti-nesting practices.
How you structure your data depends on exactly how you plan to interact with it, not just how it makes sense to look at.
Structure #1
will not work as well as Structure #2
if you ever plan on the user being able to see other users' agendas. It will still work, but the query will be much uglier.
That being said, if the agendas are visible only to their owners, then Structure #1
might make more sense simply given that fact that the organization is more intuitive to that objective. You may experience slightly faster query response times using Structure #1
as well.
There is nothing wrong with Structure #2
. If, either now or in the future, users might be able to look at other users' agendas, then Structure #2
is your best bet. Structure #2
is also better if you plan to search for agendas, across multiple users, based on one of its fields. For example, if you ever wanted to lookup the 20 most recent app-wide agenda documents by their timestamp
field.
My project has a very similar situation, with different context. Our app has Posts
and Content
. Every Post
contains one or more Content
. We could have made Content
a subcollection on each Post
(like your Structure #1
), but we instead made Content
a root-level collection (like your Structure #2
) because we needed to query Content
documents across users based on one of their fields.
In conclusion, Structure #2
is more flexible, but if you're sure that you don't want to query agendas across multiple users (collection group query) then Structure #1
may be more advantageous.
I usually default to Structure #2
except for those rare but legitimate circumstances where it really makes more sense to isolate the data to specific documents.
Upvotes: 1