正如 Doug 在他的正确答案中指出的那样,您不能让单个侦听器接收来自未知(数量或未指定)子集合的更新。
但是,如果您可以确定这些子集合名称,那么答案就很简单了。
这个想法是读取 Channels 的子节点,它们将是 channel_0、channel_1 等,并使用这些文档 id 来构建对您有兴趣收听的节点的引用。
因此,鉴于这种结构(与问题中的结构相匹配):
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"
这是为每个通道添加侦听器并响应该通道消息中的事件的代码,该消息在控制台中通知消息 ID、消息文本和事件发生的通道。
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)")
}
}
}
}
})
}
首次运行时,输出将按预期显示每个子节点。从那时起,它将输出任何添加、修改或删除。
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
代码还需要对某些选项进行一些额外的错误检查,但它应该提供解决方案。