简体   繁体   English

读取包含引用数组的 Firestore 文档

[英]Reading Firestore Document containing an array of references

Thanks in advance for the help.先谢谢您的帮助。 I'm teaching myself Swift and trying to figure out how to retrieve the following data from Firebase. Here's my Firebase Data Model...我正在自学 Swift 并试图找出如何从 Firebase 检索以下数据。这是我的 Firebase 数据 Model...

Groups (Collection) -> GroupName (String) -> Owner (References to someone in the Players collection)组(集合)-> GroupName(字符串)-> 所有者(对 Players 集合中某人的引用)

Players (Collection) -> PlayerFirstName -> PlayerLastName玩家(集合)-> PlayerFirstName -> PlayerLastName

The Swift I've written to retrieve this data is in a ViewModel.我为检索此数据而编写的 Swift 在 ViewModel 中。 getAllGroups is called from onAppear in the View and looks like this... getAllGroups 是从视图中的 onAppear 调用的,看起来像这样......

class Group: Identifiable, ObservableObject {
    var id: String = UUID().uuidString
    var name: String?
    var owner: Player?
}

class GroupViewModel: ObservableObject {

    @Published var groups = [Group]()
    private var db = Firestore.firestore()

    func getAllGroups() {
        db.collection("groups").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No groups")
                return
            }

            self.groups = documents.map { (queryDocumentSnapshot) -> Group in
                var group = Group()
                let data = queryDocumentSnapshot.data()
                group.name = data["name"] as? String ?? ""

//
// LIKE --- SHOULD THIS CALL TO GETPLAYER use AWAIT, FOR EXAMPLE?
// WE'RE EXECUTING THE CLOSURE FOR THE FIRST CALL AND ABOUT TO MAKE A SECOND
//
                group.owner = self.getPlayer(playerRef: data["owner"] as! DocumentReference)
                return group
            }
        }
    }

    func getPlayer(playerRef: DocumentReference) -> Player {

        var player = Player()
        
        playerRef.getDocument { (document, error) in
            guard error == nil else {
                print ("error", error ?? "")
                return
            }
            
            if let document = document, document.exists {
                let data = document.data()
                if let data = data {
                    player.firstName = data["firstname"] as? String
                    player.lastName = data["lastname"] as? String
                }
            }
        }

        return player
    }
}

The sorta obvious problem here is the closure for retrieving the parent Group executes and then goes and tries to retrieve the Owner.这里明显的问题是检索父组的闭包执行然后去尝试检索所有者。 But by the time the closure inside getPlayer completes... the Group has already been established.但是当 getPlayer 内的闭包完成时......该组已经建立。

Groups will have...团体将有...

group[0]
-> GroupName = "Cool Name Here"
-> Owner = nil

group[0]
-> GroupName = "Different Cool Name"
-> Owner = nil

even though each Group definitely has an Owner.即使每个组肯定有一个所有者。

I get there's some stuff here about asynchronous calls in Swift and how best to handle that... I'm just not sure what the proper pattern is.我知道这里有一些关于 Swift 中异步调用的内容,以及如何最好地处理它……我只是不确定正确的模式是什么。 Thanks again for the help and advice!再次感谢您的帮助和建议!

-j -j

To restate the question:重述问题:

How do you nest Firestore functions你如何嵌套 Firestore 函数

There are 100 ways to do it and, a lot of it depends on the use case.有 100 种方法可以做到这一点,其中很多取决于用例。 Some people like DispatchGroups, others like escaping completion handlers but in a nutshell, they pretty much do the "same thing" as the following code, written out "long hand" for readability有些人喜欢 DispatchGroups,其他人喜欢 escaping 完成处理程序,但简而言之,他们几乎做与以下代码“相同的事情”,为了可读性而写成“手写”

func populateGroupArray() {
    db.collection("groups").addSnapshotListener { (querySnapshot, error) in
        guard let docs = querySnapshot?.documents else { return }

        for doc in docs {
            let groupName = doc.get("name") as! String
            let ownerId = doc.get("owner_id") as! String
            self.addToArray(groupName: groupName, andOwnerId: ownerId)
        }
    }
}

func addToArray(groupName: String, andOwnerId: String) {
    db.collection("owners").document(andOwnerId).getDocument(completion: { snapshot, error in
        let name = snapshot?.get("owner_name") as! String
        let group = Group(groupName: groupName, ownerName: name)
        self.groups.append(group)
    })
}

In summary;总之; calling populateGroupArray reads in all of the documents from the groups collection from Firestore (adding a listener too).调用populateGroupArray从 Firestore 的组集合中读取所有文档(也添加一个监听器)。 We then iterate over the returned documents to get each group name and the owner id of the group.然后我们遍历返回的文档以获取每个组名和组的所有者 ID。

Within that iteration, the group name and ownerId are passed to another function that reads in that specific owner via it's ownerId and retrieves the name在该迭代中,组名和 ownerId 被传递给另一个 function,它通过它的 ownerId 读取该特定所有者并检索名称

Finally, a Group object is instantiated with groupName and owner name being populated.最后,组 object 被实例化,组名和所有者名称被填充。 That group is then added to a class var groups array.然后将该组添加到 class var groups 数组。

Now, if you ask a Firebaser about this method, they will generally recommend not reading large amounts of Firebase data 'in a tight loop'.现在,如果您向 Firebaser 询问此方法,他们通常会建议不要“在紧密循环中”读取大量 Firebase 数据。 That being said, this will work very well for many use cases.话虽这么说,这对于许多用例来说都非常有效。

In the case you've got a HUGE dataset, you may want to consider denormalizing your data by including the owner name in the group.如果您有一个巨大的数据集,您可能需要考虑通过在组中包含所有者名称来对数据进行非规范化。 But again, that would be a rare situation.但同样,这将是一种罕见的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Firestore 中获取引用数组? - How to get an array of references in Firestore? 如何在包含文档中对象的对象数组中搜索特定字段并在 firestore (firebase) (JS) 中更新它们 - How to search for specific fields in an array of objects containing objects in a document and update them in firestore (firebase) (JS) 如何从 Firestore 获取对文档数组的引用 - How to Get Reference to Document Array from Firestore Flutter 对文档数组字段的firestore查询 - Flutter firestore query on document array field 使用 typescript map 数组类型更新 Firestore 文档 - Updating Firestore document with typescript map array type Firestore addDoc 错误:文档参考无效。 文档引用必须有偶数个段,但 - Firestore addDoc error:Invalid document reference. Document references must have an even number of segments, but 为什么有时在 flutter 中无法按顺序从 Firestore 读取文档? - Why sometime reading document from Firestore not in order in flutter? 仅对 Firestore 中的文档进行引用吗? - Are references only for Documents in Firestore? 正在获取 Firebase Firestore 引用 - Fetching Firebase Firestore References 将数组发送到 firestore 上的存储导致读取字节长度类型错误 - Sending array to storage on firestore is causing reading bytelength typeError
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM