1

I have database structure as:

=> collection (ChatRoom) : stores chat room name, chat participants, unique chat room id
 => documents (unique ids) : documents created with unique ids based upon users
  => sub-collection (chats) : all chats going on between 2 specified persons (chat participants)

Now, i want to listen to multiple chats collection based upon user. For example :

If a user is connected with 500 people then how can i listen to those 500 chats(sub-collections) in order to get notified when a new message is being sent by any one of them.

Also, isn't that cause much of a performance overhead for the device.

Also, taking in account the db reads for such scenario, are they going to be too much.

What should be the best method for such situation ?

Fiaz Ali
  • 123
  • 11
  • I might be interested also in reading these articles, [How to query collections in Firestore under a certain path?](https://medium.com/firebase-developers/how-to-query-collections-in-firestore-under-a-certain-path-6a0d686cebd2) and [How to reduce Firestore costs?](https://medium.com/firebase-tips-tricks/how-to-reduce-firestore-costs-8cb712473e83). – Alex Mamo Sep 01 '21 at 06:43

3 Answers3

1

There is no way to listen to a self-defined set of subcollections.

Your options are:

  • Listen to the specific chats subcollections by attaching a listener to each of them.
  • Listen to all chats (sub)collections with a collection group query.
  • You can use this trick to listen to chats subcollections at a specific path in the database.

An alternative is to create a collection for each user of the data that they are supposed to see. This means you will need to write the chats in multiple location, but then reading the data for a specific user becomes much easier. This sort of trading write complexity for an easier, more scalable read is quite common when using NoSQL databases.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • I want to listen to chats sub-collection after a .where condition. Is that possible? – Fiaz Ali Aug 31 '21 at 21:33
  • Idea is to listen to those chats (sub-collections) which are only for a specified user (the user who has taken part in that chat). – Fiaz Ali Aug 31 '21 at 21:35
  • No. You will have to execute the query, and then attach a separate listener to each result. – Frank van Puffelen Aug 31 '21 at 21:36
  • What about the performance overhead in such scenario? If a user is taking part in 500 chats (sub-collections) and i attach 500 listners for all of them, isn't that going to be bad? – Fiaz Ali Aug 31 '21 at 21:38
  • Yes, so you'll have to consider what you're trying to accomplish here. A single user is unlikely to ever be looking at all 500 chats. I typically recommend to model you data closely to what you show on the user's screen. So if the user sees a list with the most recent chat message for each conversation, consider storing precisely that in a collection or maybe even a single document (for most users this will easily fit within the 1MB document size limit). I added a section to my answer about this. – Frank van Puffelen Aug 31 '21 at 21:40
  • Definitely you are right about this. No person is going to see 500 chats at once. I just want the access/listen to those chats(sub-collection) which relates to only that user who is taking part in that. The .where condition specifies that like this : FirebaseFirestore.instance.collection('ChatRoom') .where('chatRoomParticipantsList', arrayContains: chatIdentifier); – Fiaz Ali Aug 31 '21 at 21:46
  • Now, after this .where condition, if i can have access to my sub-collection, i can listen to all of the specified chats. – Fiaz Ali Aug 31 '21 at 21:48
  • I can, for example, get all the document ids(for a specific user) for the ChatRoom collection and then listen to chats(sub-collections) within them. If , let's say, there are a 1000 documents within ChatRoom collection and i retrieved 300 documents from my query, then i am going to listen to 300 chats(sub-collections). This is the thing that is getting me worried about performance. – Fiaz Ali Aug 31 '21 at 21:55
  • 1
    Listening to hundreds of collections for each user is not a scalable solution. And the API as you with for doesn't exist, precisely because it also wouldn't scale if the Firestore SDKs or servers had to do this. The approaches are outlined are the most common. I also recommend reading [NoSQL data modeling](https://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/) and watching [Getting to know Cloud Firestore](https://firestore.video), as your concerns seem more related to NoSQL data modeling in general. – Frank van Puffelen Aug 31 '21 at 21:58
  • Exactly the right point. Listening to hundreds of collections to find/notified about new data is not a scalable solution. There must be a way around to get this done. The idea was to write a chat system. Chat system, like whatsApp, always notifies when a new message is arrived. This means that in the backend, the system is actually aware/connected to the specific users data and is listening for any new data. This was the idea i was trying to implement. The exact strategy for doing this with firebase is still missing for me though. – Fiaz Ali Aug 31 '21 at 22:08
1

That's what push notifications / data messages are for. When a new message happens you send a data notification to the user's device and tell it to fetch that specific chat.

Gabriel Costache
  • 859
  • 1
  • 6
  • 17
0

So, after some long research, the limit to snapshot listeners which google recommends is 100.

Reference : Multiple streams to firebase documents without disposing

Gabriel recommendation seems to be correct on this one. When a new message from a specific user arrives, We can start attaching a listner to that specific chat. Thanks for the help and suggestions Frank.

Fiaz Ali
  • 123
  • 11