I have my Firestore setup in the following way:
Channels [collection] ----> channelID ---> Messages [collection] ---> messageID
How would I add snapshotList
I think it is because with
Firestore.firestore().collection("Channels").document().collection("Messages")
you are not defining a correct CollectionReference since you don't identify the document of the "Channels" collection.
You should do:
Firestore.firestore().collection("Channels").document(channelID).collection("Messages")
You can't have a single listener receive updates from an unknown number of subcollection. There are no "wildcard" operators for listeners on collections. You have to choose a specific collection or query and attach a listener to that.
As Doug pointed out in his correct answer, you cannot have a single listener receive updates from an unknown (number of or unspecified) subcollection.
However, if you can determine those subcollection names, then the answer is pretty straightforward.
The idea is to read the child nodes of Channels, which will be channel_0, channel_1 etc and use those document id's to build references to the nodes you are interested in listening to.
So given this struture (which matches the structure in the question):
Channels
channel_0
Messages
message_0
msg: "chan 0 msg 0"
message_1
msg: "chan 0 msg 1"
message_2
msg: "chan 0 msg 2"
channel_1
Messages
message_0
msg: "chan 1 msg 0"
message_1
msg: "chan 1 msg 1"
Here's the code that adds listeners to each channel, and responds to events within that channels messages notifying in console the message id, msg text and the channel the event occurred in.
func addChannelCollectionObserver() {
let channelsRef = self.db.collection("Channels")
channelsRef.getDocuments(completion: { snapshot, error in
guard let documents = snapshot?.documents else {
print("Collection was empty")
return
}
for doc in documents {
let docID = doc.documentID
let eachChannelRef = channelsRef.document(docID)
let messagesRef = eachChannelRef.collection("Messages")
messagesRef.addSnapshotListener { querySnapshot, error in
querySnapshot?.documentChanges.forEach { diff in
if diff.type == .added {
let doc = diff.document
let msgId = doc.documentID
let channelId = messagesRef.parent!.documentID
let msg = doc.get("msg") as? String ?? "no message"
print(" added msgId: \(msgId) with msg: \(msg) in channel: \(channelId)")
}
if diff.type == .modified {
let doc = diff.document
let msgId = doc.documentID
let msg = doc.get("msg") as? String ?? "no message"
print(" modified msgId: \(msgId) with msg: \(msg)")
}
if diff.type == .removed {
let doc = diff.document
let msgId = doc.documentID
let msg = doc.get("msg") as? String ?? "no message"
print(" removed msgId: \(msgId) with msg: \(msg)")
}
}
}
}
})
}
When first run the output will show, as expected, each child node. From then on it will output any addititions, modifications or deletions.
added msgId: message_0 with msg: chan 0 msg 0 in channel: channel_0
added msgId: message_1 with msg: chan 0 msg 1 in channel: channel_0
added msgId: message_2 with msg: chan 0 msg 2 in channel: channel_0
added msgId: message_0 with msg: chan 1 msg 0 in channel: channel_1
added msgId: message_1 with msg: chan 1 msg 1 in channel: channel_1
the code needs some additional error checking as well for some of the optionals but it should provide a solution.
use collection group query for this by listening to all the collections with the same name
db.collectionGroup("Messages"). docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
@Override
public void onEvent(@Nullable DocumentSnapshot snapshot,
@Nullable FirestoreException e) {
if (snapshot != null && snapshot.exists()) {
System.out.println("Current data: " + snapshot.getData());
} else {
System.out.print("Current data: null");
}
}
});