Firestore listener for sub collections

前端 未结 4 967
闹比i
闹比i 2021-01-13 09:05

I have my Firestore setup in the following way:

Channels [collection] ----> channelID ---> Messages [collection] ---> messageID

How would I add snapshotList

4条回答
  •  孤独总比滥情好
    2021-01-13 10:02

    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.

提交回复
热议问题