Question
Firestore subcollection vs array
First of, I know how Firestore works and have spent a lot of time, evaluating different approaches for a good structure. Still I am considering following scenario:
There is a database of recipes. Users can add recipes. Every user can choose from the user-generated list of recipes to state which ones they know how to cook.
Now I want users to share their list of recipes with others. This is where I am not sure how this can be best accomplished using Firestore. The trick is, that I want to show all the recipes at once, and don't want to paginate them.
I am currently evaluating two possibilities:
Subcollections
Whenever a user shares his list, the user looking at said list will have to load the entire list of the recipes which can result in a high amount of document reads (I suppose realistically ~50, in very rare cases maybe 1000).
Pros:
- More natural structure
- Easier to maintain (e.g. deleting a recipe, checking if a specific one exists)
- Easier to add fields (e.g. timeOfCreation, comment, personalRating, ...)
Cons:
- Can result in a high amount of reads on the long run
Arrays
I could save every known recipe (the id and an imageURL) inside the user's document (or as a single subdocument "KnownRecipes") within an array. This array could be in form of
recipesKnown: [{rid: 293ndwa, imageURL: image1.com, timeAdded: 8371201332},
{rid: 9012831, imageURL: image1.com, timeAdded: 8371201871},
{rid: jd812da, imageURL: image1.com, timeAdded: 8371201118},
...
]
Pros:
- I only need one document read whenever someone wants to see another user's list
- Reading a user's list is probably faster
Cons:
- It's hard to update a specific recipe (e.g. someone wants to change the imageURL: I need to change the list locally and send the entire document as an update to the server - since I cannot just change a single element in the array)
- When a user decides to have around 1000 recipes (this will maybe never happen, but it could), the 1MiB limit of the Firestore limit could be reached. A possible workaround would be to create a seperate document and split those two arrays into these two documents.
For me, the idea with Subcollections seems to be the more "clean" solution to this problem, but maybe I am missing some arguments on why one of those solutions would be superior over the other.
My most common queries are as follows (ordered descending by importance):
- Which recipes can a user cook
- Add a recipe a user can cook to the user's list
- Who can cook a specific recipe (there is a Recipe -> Cooks subcollection)
- Update an existing recipe a user can cook