gpt4 book ai didi

ios - Swift:Firestore 子集合、自定义对象和监听器

转载 作者:行者123 更新时间:2023-11-28 11:37:19 24 4
gpt4 key购买 nike

我有一个模型模式,如下图所示。

Model

在 UI 中,我试图获取所有 Countries 和相关数据。我已经创建了各自的结构,我的想法是使用链接 Custom_Objects 中显示的自定义对象方法。 .现在我遇到的问题是 subcollections 不会出现在 querysnapshot 中(我只得到字段)因此我不能进行直接对象映射(因为我有查询和检索子集合以使对象完整)。例如:Country 结构具有 States 作为属性之一,没有状态 Country 对象无法创建和 States进一步有省份。现在我正在做递归循环来构建我感觉不太好的整个结构。

所以我的问题是,处理这种数据的最佳方式是什么(假设没有规范化的空间并且我们无法避免子集合)?

此外,如果我想收到有关州、省或镇的任何更改的通知,我是否需要分别向每个集合添加监听器或添加到根就足够了?

这是当前的代码快照

    db.collection("countries").getDocuments { (QuerySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
}else{
var docCount = QuerySnapshot!.documents.count
for document in QuerySnapshot!.documents {
self.fetchStatesForDoc(document: document, completion: { (nodes) in
var data = document.data()
data["states"] = nodes
let country = Country(dictionary: data)
self.countryList.append(country!)
print(self.sectionList)
docCount = docCount - 1
if docCount == 0{
DispatchQueue.main.async {
self.countryCollection.reloadData()
}
}
})
}
}
}
}
func fetchStatesForDoc(document: DocumentSnapshot, completion:@escaping ([State])-> Void){

var states = [State]()
document.reference.collection("states").getDocuments(completion: { (QuerySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
}else{
var docCount = QuerySnapshot!.documents.count
for document in QuerySnapshot!.documents {
//print("\(document.documentID) => \(document.data())")
var data = document.data()
self.fetchProvincesForDoc(document: document, completion: { (provinces) in
data["Provinces"] = provinces
let state = State(dictionary: data)
states.append(state!)
docCount = docCount - 1
if docCount == 0{
completion(state)
}
})
}
}
})
}
func fetchProvincesForDoc(document: DocumentSnapshot, completion:@escaping ([Province])-> Void){

var provinces = [Province]()
document.reference.collection("provinces").getDocuments(completion: { (QuerySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
}else{
var docCount = QuerySnapshot!.documents.count
for document in QuerySnapshot!.documents {
//print("\(document.documentID) => \(document.data())")
var data = document.data()
self.fetchTownsForDoc(document: document, completion: { (towns) in
data["towns"] = provinces
let province = Province(dictionary: data)
provinces.append(province!)
docCount = docCount - 1
if docCount == 0{
completion(province)
}
})
}
}
})
}
func fetchTownssForDoc(document: DocumentSnapshot, completion:@escaping ([Towns])-> Void) {

var towns = [Towns]()
document.reference.collection("towns").getDocuments(completion: { (QuerySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
}else{
for document in QuerySnapshot!.documents {
//print("\(document.documentID) => \(document.data())")
}
towns = QuerySnapshot!.documents.compactMap({Towns(dictionary: $0.data())})
completion(towns)
}
})
}

最佳答案

Now the problem I have is that subcollections wont come in the querysnapshot ( I am getting only the fields)

没错,这就是 Cloud Firestore 查询的工作原理。这些查询被命名为 shallow,这意味着它们只从运行查询的集合中获取项目。无法在单个查询中从顶级集合和子集合中获取文档。 Firestore 不支持一次跨不同集合的查询。单个查询只能使用单个集合中文档的属性。这就是为什么 ypu 看不到 querysnapshot 对象中的子集合,因此您可以进行直接对象映射。

what is the best way to handle these kind of data (provided there is no room for normalization and we cant avoid subcollections)?

在这种情况下,您应该查询数据库两次,一次是获取集合中的对象,第二次是获取子集合中的所有对象。

还有另一种做法称为非规范化,是 Firebase 的常见做法。此技术还意味着查询数据库两次。如果您是 NoQSL 数据库的新手,我建议您观看此视频,Denormalization is normal with the Firebase Database为了更好地理解。它适用于 Firebase 实时数据库,但同样的规则适用于 Cloud Firestore。

此外,当您复制数据时,需要牢记一件事。以与添加数据相同的方式,您需要维护它。换句话说,如果你想更新/删除一个项目,你需要在它存在的每个地方进行。

因此在这种情况下,您可以通过创建一个顶级集合来对数据进行反规范化,您应该在其中添加子集合中存在的所有对象。由您决定哪种做法更适合您。

关于ios - Swift:Firestore 子集合、自定义对象和监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54751023/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com