I am working on a management app for local groups.
The app also displays each group its contacts list.
I wonder how should I design my database?
If I store all users on a root level collection, each time a user opens the contacts list it will read all his group's users' documents. Assuming 1000 contacts groups, for example, adds up to A LOT of reads for a simple task like that.
The same goes for using a subcollection for the group.
Storing the group's contacts in the group's document as a map is not scalable.
And the same goes for using a map in the group's document to index a collection or a subcollection in a denormalized model.
And this is where I'm stuck.
Am I missing something or that these are the options I have and I need to choose between a large number of reads each time a user opens the contacts list and a model designed for limited sized groups?
I think this is a common situation. Many items are related to fewer parent items, and we want to show the parent item's children.
For Firestore, it's recommended that you limit your queries.
For example, if a user wants to see the groups' contact list, that's fine, make a query. But don't show all 1000+ contacts at once. Even Facebook doesn't do that (go to a Facebook group and click on "Members", you'll only be shown a dozen or so, and as you scroll down, more queries are made to show you more.)
Users expect this kind of behavior: lazy loading or pagination.
Documentation for Firestore to limit/paginate queries: limit, paginate
This way, groups can be documents, and contacts can be documents that have an Array field that contains the group-id's they belong to. To display a group's contacts, you can use an "array-contains" query on the contacts collection.
Something like this
contacts (collection)
|
--- {contactId} (document)
|
--- (...contact data...)
|
--- group_membership (array)
|
0--- 'groupId111'
|
1--- 'groupId222'
(For the contacts(col)/contact(doc)/group_membership(field) I'm assuming a contact can belong to multiple groups if this is not the case, the field can be a string instead of an array, but it's safer to make it an array in case you change your mind.)
All I'm getting at here is that your vision for the db structure is fine and common, you don't have to restructure just to avoid querying a thousand contact documents... because you don't have to. You don't have to query 100 times the amount of data that your end-user will actually need.