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
 48  10946  48
1 Jan 1970

Solution

 9

The answer to your question depends on the level of scalability you want to achieve.

If by design the amount of sub-data you want to store is limited and very low, you should use arrays, since you reduce the number of document reads, which means lower costs.

If your sub-data is supposed to increase "unlimitedly" over time, you should use sub-collections.

If you're building a database which is not supposed to scale in any direction (Proof of concept, very small business, etc.) just go with what you feel more comfortable with.

2020-12-20

Solution

 4

I'm researching the same question...

One of the questions is whether the data held in the document will be ever go pass 1MB that is the limit for a document. Researching a bit on how much it can be held in plain text in 1MB well it's a hell of a lot. Still if it were to be incredible bigger it would crash in the end. Thus if you think in a big-big way sub-collections.

If we had to use the Firebase element logic the answer would be sub-collections.

Still I guess the major point is the data pulled. If you call the user you will directly be pulling out that MB of data. Instead with a sub-collection it won't load, even if you loaded it you can still lazy-load.

I guess for the kind of setup you are doing sub-collections.

2020-10-04