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



提前感谢您的帮助。我正在自学Swift,并试图弄清楚如何从Firebase中检索以下数据。这是我的Firebase数据模型。。。

组(集合(->GroupName(字符串(->所有者(引用玩家收藏中的某个人(

玩家(收藏(->玩家名字->玩家姓氏

我为检索这些数据而编写的Swift位于ViewModel中。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
}
}

这里的sorta明显问题是检索父组的闭包执行,然后执行并尝试检索所有者。但是当getPlayer内部的关闭完成时。。。该小组已经成立。

组将具有。。。

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

即使每个组都有一个所有者。

我了解到一些关于Swift中异步调用的内容,以及如何最好地处理这些内容。。。我只是不确定合适的模式是什么。再次感谢您的帮助和建议!

-j

重述问题:

如何嵌套Firestore函数

有100种方法可以做到这一点,其中很大一部分取决于用例。有些人喜欢DispatchGroups,有些人喜欢转义完成处理程序,但简而言之;同样的事情";作为下面的代码;"长手";可读性

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

总之;调用populateGroupArray从Firestore读取groups集合中的所有文档(还添加了一个侦听器(。然后,我们对返回的文档进行迭代,以获得每个组的名称和组的所有者id。

在该迭代中,组名称和所有者ID被传递给另一个函数,该函数通过其所有者ID读取特定所有者并检索名称

最后,使用正在填充的groupName和所有者名称来实例化Group对象。然后将该组添加到类var组数组中。

现在,如果你向Firebaser询问这种方法,他们通常会建议不要"在一个紧密的循环中"读取大量的Firebase数据。话虽如此,这将非常适用于许多用例。

如果您有一个庞大的数据集,您可能需要考虑通过在组中包含所有者名称来取消数据规范化。但同样,这将是一种罕见的情况。

最新更新