1

I'm actually trying to find the most efficient way to reduce the number of read in my Firebase app.

Instead of creating a new document for each object, i was thinking about insert each object inside a new field of the same document.

Here is a typical object that i use in my app :

{
 "restaurantName" : "The Love story",
 "openingTimes" : {"opening" : "9AM", "closing" : "11pm"},
 "numberOfReviews" : 2340
}

According to Firebase the limit of size for a document is 1MB, which is enough to put around 2000 object in my case.

By making a snapshot on one single document, i'm able to read all the fields of the document with this path: payload['_document']['proto']['fields']

this.afs.collection('MyCollection').doc('restaurantName').snapshotChanges().subscribe(data => {
  console.log('All the fields of my doc = ', payload['_document']['proto']['fields'])
});

This seems to be working fine and only count as 1 document read each time a change occur in the document right ?

This approach is way cheaper than loading X documents, but something tells me that this is not a good practice.

Is there any reasons why i shouldn't go with this approach ?

Thank you

creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
Julie Rankata
  • 774
  • 8
  • 12

2 Answers2

2

I think this is a bad practice:

Cloud Firestore always downloads full documents

Imagine having a few thousand fields in a document and a few users contribute to this document and change fields there every second. In just a minute, you will have 60 MB (!) of data usage for this one document per user.

If you had split this up into multiple documents, you would have had only 1 MB per user at max. Most of the time, the users will have at least some of the documents cached already, which means this will further decrease usage again.

Firestore is not optimized for it

As I already touched on, cache will not work at all. Even if 99% of the fields stay the same, all of these values will be updated every time another field changes.

This will also negatively impact queries because they are built for multiple documents.

You will pay more

Cloud Firestore is optimized for document reads - they are not very expensive. Bandwidth, however, is expensive:

See pricing at Firebase pricing and for network costs (which you also have to pay and have a free quota for) Google Cloud pricing:

So in the case above, we can clearly see that the difference can easily be two orders of magnitude (MB egress to K reads) larger, however, for just equal pricing, only one order of magnitude is allowed. I could easily imagine you paying 10 times more using your method and this can be worth depending on the region.

Btw, I might have gotten the exact pricing wrong. You can find that Cloud Firestore requests are also billable based on bandwidth here and obviously on the App Engine Quotas page for your project.

creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
  • Oh yes... i forgot to take in consideration the bandwidth ! Thank you for taking time to answer, i will stick to the 'normal' approach :) – Julie Rankata Mar 08 '20 at 13:01
0

As soon as you don't go over the 1MB size limit for the document there is nothing that technically prevents you adopting this approach.

However, you may encounter some other limitations/complexity with this data model:

  • What if you want to query only for one restaurant? Are you going to download the data of the 2000 restaurants just for getting the values of one of them?
  • Depending on the way you store your restaurant objects collection (array or map) you may need to download the entire collection if you want to update only one element of one restaurant.
Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • Yes i was planning to download the whole collection each time a user visit the app. Doing so the user can check any restaurant without any latency. – Julie Rankata Mar 08 '20 at 12:20