Firestore listener for sub collections

前端 未结 4 934
闹比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 09:40

    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")
    
    0 讨论(0)
  • 2021-01-13 09:49

    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.

    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2021-01-13 10:03

    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");
        }
      }
    });
    
    0 讨论(0)
提交回复
热议问题