swift firebase嵌套子计数

时间:2017-11-15 15:18:51

标签: swift firebase firebase-realtime-database

groups
--group1(autoid)
---subgroup1(autoid)
----id
----ownerId
----description
--group2(autoid)
---subgroup2(autoid)
----id
----ownerId
----description

在像这里这样的结构中,我必须计算所有组中所有与我的id(currentUserId)相等的ownerId的出现次数,有人可以帮助我吗?

到目前为止我做了什么:

root.child("groups").observe(.value, with: {(snapshot) in
    if let result = snapshot.children.allObjects as? [DataSnapshot] {
        var count = 0
        for child in result {
            let orderID = child.key as String //get autoID
            self.root.child("groups/\(orderID)/").queryOrdered(byChild: "ownerId").queryEqual(toValue: self.currentUserId).observe(.value, with: { (snapshot: DataSnapshot!) in
                print(snapshot.childrenCount, "quanti sono")
                count += (Int(snapshot.childrenCount))
                print(count)
            })
        }
    }
})

有了这个我可以得到一个计数,但它更新所有周期...我需要我需要外面的最终值

2 个答案:

答案 0 :(得分:1)

Firebase结构的一个重要方面是denormalizing或展平结构。非规范化数据通常使查询更容易,而从概念上讲,您使用的结构适用于某些任务,它使得您想要的查询具有挑战性。

因此,我建议使用一种替代结构,使查询变得非常简单,而不会松散其他功能。

改变结构如下:

groups
  group1: true
  group2: true

subgroups
  subgroup1(autoid)
     id
     ownerId
     description
     belongs_to_group: "group1"
  subgroup2(autoid)
     id
     ownerId
     description
     belongs_to_group: "group2"

然后,如果要计算具有特定ownerId

的所有子组
let subGroupsRef = self.ref.child("subgroups")
let query = subGroupsRef.queryOrdered(byChild: "ownerId").queryEqual(toValue: "their id")
query.observeSingleEvent(of: .value) { snapshot in
    let count = snapshot.childrenCount
    print(count)
}

修改

根据评论,这是根据您当前的结构获取计数的方法。这是相当暴力的,代码可以大大减少,但我留下了冗长的可读性

let groupsRef = self.ref.child("groups")
groupsRef.observeSingleEvent(of: .value, with: { snapshot in
    var count = 0
    for groupChild in snapshot.children {
        let groupSnap = groupChild as! DataSnapshot
        for subGroupChild in groupSnap.children {
            let subGroupSnap = subGroupChild as! DataSnapshot
            let dict = subGroupSnap.value as! [String: Any]
            let uid = dict["owner_id"] as! String
            if uid == "uid_0" {
                count += 1
                print(count)
            }
        }
    }
    print("total found \(count)")
})

如果失败的话,如果你有很多节点,因为它们最初都被加载(通过.value),所以它可以在代码中迭代。如果它是几千,它运作良好,并且非常快。

答案 1 :(得分:0)

您可以通过执行observe .childAdded.childAdded类型来完成此步骤。在您的示例groups中,子子节点上的.queryOrdered(byChild:)类似于迭代所有节点的for循环。

使用此配置,您可以附加.queryEqual(toValue:)ref.child("groups") .queryOrdered(byChild: "ownerID") .queryEqual(toValue: 123) .observe(.childAdded) { (snap) in print(snap) }

.indexOn

之后,如果你想计算所有这个孩子,你需要在你的班级上添加一个属性

这是一个测试示例:

要优化性能,请记住在firebase应用上添加"groups" : { ".indexOn" : "ownerID" } 规则:

grid.emplace_back(Cell{1,false, row,col});   

希望这能帮到你;)