代码之家  ›  专栏  ›  技术社区  ›  anoop4real

Swift:Firestore子集合、自定义对象和侦听器

  •  0
  • anoop4real  · 技术社区  · 6 年前

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

    Model

    Countries 以及相关数据。我已经创建了各自的结构,我的想法是使用链接中显示的自定义对象方法 Custom_Objects . 现在我的问题是 subcollections 我不会进来的 querysnapshot (我只获取字段),因此我无法进行直接对象映射(因为我必须查询和检索子集合才能使对象完整)。例如: 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)
            }
        })
    }
    
    0 回复  |  直到 6 年前
        1
  •  3
  •   Alex Mamo    6 年前

    没错,这就是云Firestore查询的工作原理。这些查询被命名为shallow,这意味着它们只从运行查询的集合中获取项。无法在单个查询中从顶级集合和子集合获取文档。Firestore不支持一次查询不同集合。单个查询只能使用单个集合中文档的属性。这就是ypu无法在中看到子集合的原因 querysnapshot

    处理此类数据的最佳方法是什么(前提是没有标准化的空间,我们无法避免子集合)?

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

    Denormalization is normal with the Firebase Database 为了更好的理解。它适用于Firebase实时数据库,但同样的规则适用于云Firestore。

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