I have a group chat feature in my app that has its messages node structured like this. Currently, it doesn't use the fan-out technique. It just lists all of the messages under the group name e.g. "group1"
groups: {
group1: {
-MEt4K5xhsYL33anhXpP: {
fromUid: "diidssm......."
userImage: "https://firebasestorage..."
text: "hello"
date: 1617919946
emojis: {
"heart": 2
"like": 1
}
}
-MEt8BLP2yMEUMPbG2zV: {
...
}
-MF-Grpl8Jchxpbn2mxH: {
...
}
-MF-OUjWXsFh7lBPosMf: {
...
}
}
}
I first observe the most recent 40 messages and observe whether new children get added as such
ref = Database.database().reference().child("groups").child("group1")
ref.queryLimited(toLast: 40).observe(.childAdded, with: { (snapshot) in
...
//add to messages array to load collection view
//for each message observe emojis and update emojis to reflect changes e.g. +1 like
ref.child("emojis").observe(.value, with: { (snapshot) in
...
})
})
Every time the user scrolls up I load another 40 messages (and observe the emojis child under each of those message nodes) using the last date (and index by date in security rules) as such
ref.queryOrdered(byChild: "date").queryEnding(beforeValue: prevdate, childKey: messageId).queryLimited(toLast: 40).observeSingleEvent(of: .value, with: { (snapshot) in
I understand the fan-out technique is used to get less information per synchronization. If I attach a listener to the groups/groupname/ to get a list of all messages for that group, I will also ask for all the info of each and every message under that node. With the fan out approach I can also just ask for the message information of the 40 most recent messages and the next 40 per scroll up using the keys of the messages from another node like this.
allGroups: {
group1: {
-MEt4K5xhsYL33anhXpP: 1
-MEt8BLP2yMEUMPbG2zV: 1
-MF-Grpl8Jchxpbn2mxH: 1
-MF-OUjWXsFh7lBPosMf: 1
}
}
However, if I am using queryLimited(toLast: 40) is the fan-out approach beneficial or even necessary? Wouldn't this fix the problem of "I will also ask for all the info of each and every message under that node"?
In terms of checking for new messages, I just check using .childAdded in the first code above (ref.queryLimited(toLast: 40).observe(.childAdded)). According to the post below, queryLimited(toLast: 40) will sync the last 40 child nodes, and keep synchronizing those (removing previous ones as new ones are added).
Some questions about keepSynced(true) on a limited query reference
I'm assuming if group1 had 1000 messages, with this approach I am just reading the 40 most recent messages I need and the next 40 per scroll, thus ignoring the other several hundred. Why would I use the fan-out technique then? May be I'm not understanding something fundamental about limited queries.
Side Question: Should I be including references to profile images under each message node? Is it bad to do this in terms of cloud storage and realtime database storage? Ideally there would be hundreds of groupchats.