代码之家  ›  专栏  ›  技术社区  ›  OuSS

子集合的Firestore侦听器

  •  2
  • OuSS  · 技术社区  · 6 年前

    我的Firestore设置如下:

    频道[收藏]----->channelID--->消息[收集]——> 消息ID

    如何将snapshotListener添加到子集合“消息”中?

      Firestore.firestore().collection("Channels").document().collection("Messages").addSnapshotListener { (querySnapshot, error) in
            guard let snapshot = querySnapshot else {
                print("Error listening for channel updates: \(error?.localizedDescription ?? "No error")")
                return
            }
    
            snapshot.documentChanges.forEach { change in 
               print(change)
            }
        }
    

    这对我不管用

    3 回复  |  直到 6 年前
        1
  •  0
  •   Renaud Tarnec    6 年前

    我想是因为

    Firestore.firestore().collection("Channels").document().collection("Messages")
    

    你没有定义一个正确的 CollectionReference 因为您没有识别“通道”集合的文档。

    你应该做:

    Firestore.firestore().collection("Channels").document(channelID).collection("Messages")
    
        2
  •  4
  •   Jay    6 年前

    正如Doug在正确答案中指出的那样,您不能让一个侦听器从未知(数量或未指定)子集合接收更新。

    然而,如果你能确定这些子集合的名称,那么答案就相当简单了。

    其思想是读取通道的子节点,即通道0、通道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
    

    对于一些选项,代码还需要一些额外的错误检查,但它应该提供一个解决方案。

        3
  •  5
  •   Doug Stevenson    6 年前

    不能让一个侦听器从未知数量的子集合接收更新。集合上的侦听器没有“通配符”运算符。您必须选择一个特定的集合或查询,并为其附加一个侦听器。

        4
  •  1
  •   Artur A    3 年前

    如果你想 订阅Firstore子集合更改 在后端,这里是来自 Firebase docs :

    // Listen for changes in all documents in the 'users' collection and all subcollections
    exports.useMultipleWildcards = functions.firestore
        .document('users/{userId}/{messageCollectionId}/{messageId}')
        .onWrite((change, context) => {
          // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
          // context.params.userId == "marie";
          // context.params.messageCollectionId == "incoming_messages";
          // context.params.messageId == "134";
          // ... and ...
          // change.after.data() == {body: "Hello"}
        });
    

    请注意,即使是子集合名称也可以与通配符一起使用 {messageCollectionId} 任何地下采集 用户集合的一部分。

    根据问题 Channels [collection] ----> channelID ---> Messages [collection] ---> messageID 代码可以是:

    exports.onMessagesSubcollectionChange = functions.firestore
        .document('Channels/{channelID}/Messages/{messageID}')
        .onWrite((change, context) => {
       // the rest code
       // context.params.channelID
       // and context.params.messageID will be fulfilled.
    }
    

    不确定客户端是否支持它。

        5
  •  3
  •   akhil    5 年前

    使用 collection group query 为此,请收听所有同名集合

        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");
        }
      }
    });