有没有办法在查询主集合时将子集合映射到结构? (火库)

Posted

技术标签:

【中文标题】有没有办法在查询主集合时将子集合映射到结构? (火库)【英文标题】:Is there a way to map a sub-collection into a struct while querying the main collection? (Firestore) 【发布时间】:2021-10-12 18:35:18 【问题描述】:

有没有办法在查询主集合时将子集合映射到结构中?

我的子集合结构是:

-conversations (collection)
--- "users" : [array of two users]
--- messages (subcollection)
------- "created by": "sender"
------- "date" : timestamp
------- "msg" : "help me guys I'm stuck with this damn chat feature"

我在某处读到查询很浅,这意味着您只会获得您正在查询的集合的字段,但也许在查询第一个集合之后除了嵌套查询循环之外还有另一种方法

func getFilteredConversations(query: String) 
        
        if (user != nil) 
            db.collection("conversations").whereField("users", arrayContains: user!.displayName)
                .order(by: "createdTime")
                .addSnapshotListener  (querySnapshot, error) in
                    guard let documents = querySnapshot?.documents else 
                        print("no conversations found")
                        return
                    
                    
                    //mapping
                    self.chats = documents.map (queryDocumentSnapshot) -> Conversation in
                        
                        let data = queryDocumentSnapshot.data()
                        let docId = queryDocumentSnapshot.documentID
                        let users = data["users"] as? [String] ?? [""]
                        let unreadmsg = data["hasUnreadMessage"] as? Bool ?? false
                        
                        //MARK: - GET MESSAGES
                        self.db.collection("conversations").document(docId).collection("messages")
                            .order(by: "date")
                            .addSnapshotListener (querySnapshot, err) in
                                
                                guard let documents = querySnapshot?.documents else 
                                    print("no messages found")
                                    return
                                
                                
                                var mensajes = [Message]()
                                
                                mensajes = documents.map (queryDocumentSnapshot) -> Message in
                                    
                                    let data = queryDocumentSnapshot.data()
                                    let docId = queryDocumentSnapshot.documentID
                                    let createdby = data["created_by"] as? String ?? ""
                                    let msg = data["msg"] as? String ?? ""
                                    let date = data["date"] as? Timestamp ?? Timestamp()
                                    
                                    return Message(createdBy: createdby, msg: msg, date: date, id: docId)
                                    
                                
                            
                        
                        print("Users: \(users)")
                        
                        return Conversation(id: docId, users: users, messages: mensajes, hasUnreadMessage: unreadmsg)
                        
                    
                
        
    

这是模型

struct Conversation: Decodable, Identifiable 
    //var id: UUID  person.id 
    @DocumentID var id: String? = UUID().uuidString
    var users: [String] = [""]
    var messages: [Message] = []
    var hasUnreadMessage : Bool = false


struct Message: Decodable 
    var createdBy: String?
    var msg: String?
    @ServerTimestamp var date : Timestamp?
    var id : String?

【问题讨论】:

【参考方案1】:

您自己似乎已经找到了答案:Firestore 查询很浅。在读取父文档时无法从子集合中读取。跨集合查询的唯一方法是使用collection group query,这似乎不适用于此处。

考虑是否值得通过客户端代码或云函数在父文档中复制来自对话的最新消息。这样,您就可以减少为向用户显示初始消息而必须阅读的文档数量。

【讨论】:

感谢您的回答,我只想在每次聊天中添加新消息时获得实时更新。集合组查询会完成吗?或者我应该为每个聊天/对话添加一个听众?我知道我最多有 100 个 要更新特定对话的消息,您可以收听 messages 子集合。要跨多个对话收听,收集组查询或将数据复制到父文档中是您的两个选择 - 正如我的回答中所述。

以上是关于有没有办法在查询主集合时将子集合映射到结构? (火库)的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法获取子集合中的所有文档(Firestore)

停止加载子集合,如果我更新父集合

是否可以检查集合或子集合是否存在?

Firestore 对集合及其文档的子集合进行过滤

Firebase 查询集合和合并子集合数据

Firestore:获取带有和不带有子集合数据的集合[重复]