Reputation: 111
I'm using a two-collection approach (userChats
and chats
) for quickly accessing a user's group chats as opposed to the use of an extremely long participant array of user IDs. However, I am struggling with efficiently showing which chats in listview in order of recent activity like the latest message.
// Quick access to user's chats to avoid querying large participant arrays
userChats/{userId}/chats/{chatId} {
joinedAt: Timestamp
}
// Main chat data
chats/{chatId} {
lastMessageAt: Timestamp,
participantCount: int,
participants: {
[userId]: true // For membership checks
}
}
When loading a user's chat list with pagination, I've hit a fundamental issue:
joinedAt
in userChats
:final userChats = await firestore
.collection('userChats')
.doc(userId)
.collection('chats')
.orderBy('joinedAt', descending: true)
.limit(20)
.get();
Issue: Active chats that the user joined long ago appear at the bottom of their paginated list, requiring users to scroll through potentially hundreds of chats to see new activity. There is the obvious point that 'joinedAt' is not lastMessageSent Time
lastMessageAt
to userChats
to order by recent activity:userChats/{userId}/chats/{chatId} {
joinedAt: Timestamp,
lastMessageAt: Timestamp // Mirror from main chat
}
Issue: Every new message requires updating all participants' userChats
documents (1000+ writes per message).
What's the most efficient Firestore schema to show users their recently active chats while:
Upvotes: 0
Views: 34
Reputation: 139019
Without having the lastMessageAt
field inside the "chat" document, there is no way you can filter and order your chats. Firestore cannot perform such operation on non-existing fields or on fields that exist in some other parts of the database.
It's true that to have such functionality you have to update the lastMessageAt
field each time a new message is added in each chat, but it's a trade between having this functionality or not having it at all.
In such cases, I recommend you notice that Firebase has another similar scalable NoSQL real-time database which is called the Realtime Database. This database has a billing mechanism different from that of Firestore. So you’re charged for bandwidth and not for reads and writes you perform. So you might take this option into consideration.
Upvotes: 0