子集合的 Firestore 侦听器

OuS*_*uSS 7 ios firebase swift google-cloud-firestore

我的 Firestore 设置如下:

频道[集合] ----> 频道ID ---> 消息[集合] ---> 消息ID

我如何将 snapshotListener 添加到子集合 'Messages' ?

  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)
        }
    }
Run Code Online (Sandbox Code Playgroud)

这对我不起作用

Dou*_*son 5

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


Jay*_*Jay 5

正如 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"
Run Code Online (Sandbox Code Playgroud)

下面的代码向每个通道添加侦听器,并响应该通道消息中的事件,在控制台中通知消息 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)")
                    }
                }
            }
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

首次运行时,输出将按预期显示每个子节点。从那时起它将输出任何添加、修改或删除。

 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
Run Code Online (Sandbox Code Playgroud)

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


Ren*_*nec 1

我认为这是因为

Firestore.firestore().collection("Channels").document().collection("Messages")
Run Code Online (Sandbox Code Playgroud)

您没有定义正确的CollectionReference,因为您没有识别“Channels”集合的文档。

你应该做:

Firestore.firestore().collection("Channels").document(channelID).collection("Messages")
Run Code Online (Sandbox Code Playgroud)