swift firebase嵌套子项计数

swift firebase嵌套子项计数,swift,firebase,firebase-realtime-database,Swift,Firebase,Firebase Realtime Database,在这里这样的一个结构中,我必须计算所有组中ownerId等于我的id(currentUserId)的所有发生率,有人能帮我吗 到目前为止我所做的: root.child(“组”).observe(.value,其中:{(快照)位于 如果let result=snapshot.children.allObjects as?[DataSnapshot]{ 变量计数=0 为了孩子{ 让orderID=child.key作为字符串//获取自动ID self.root.child(“groups/\(or

在这里这样的一个结构中,我必须计算所有组中ownerId等于我的id(currentUserId)的所有发生率,有人能帮我吗

到目前为止我所做的:

root.child(“组”).observe(.value,其中:{(快照)位于
如果let result=snapshot.children.allObjects as?[DataSnapshot]{
变量计数=0
为了孩子{
让orderID=child.key作为字符串//获取自动ID
self.root.child(“groups/\(orderID)/”).queryOrdered(byChild:“ownerId”).queryEqual(toValue:self.currentUserId)。观察(.value,其中:{(快照:DataSnapshot!))
打印(snapshot.childrenCount,“quanti-sono”)
计数+=(Int(快照.子计数))
打印(计数)
})
}
}
})

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

您可以通过执行
的单个
观察
.childAdded
类型来实现此步骤。在您的示例中,
.childAdded
子节点上的
.childAdded
类似于迭代所有节点的for循环

使用此配置,您可以附加一个
.queryOrdered(byChild:)
和一个
.queryEqual(toValue:)

之后,如果要计算所有子级,则需要在类上添加属性

这是一个测试示例:

要优化性能,请记住在firebase应用程序上添加
.indexOn
规则:

ref.child("groups")
    .queryOrdered(byChild: "ownerID")
    .queryEqual(toValue: 123)
    .observe(.childAdded)
{ (snap) in
    print(snap)
}

希望这对你有帮助;)

火基结构的一个重要方面是对结构进行加固或整平。非规范化数据通常会使查询变得更容易,虽然从概念上讲,您正在使用的结构适用于某些任务,但它会使执行您想要的查询变得具有挑战性

因此,我建议使用另一种结构,使查询变得超级简单,而不会失去其他功能

对结构的更改如下:

"groups" : {
  ".indexOn" : "ownerID"
}
然后,如果要计算具有特定所有者ID的所有子组

groups
  group1: true
  group2: true

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

根据评论,这里有一种根据您当前的结构获取计数的方法。这是一个非常强大的工具,代码可以大大减少,但是为了可读性,我把它放在了冗长的地方

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

失败的地方是,如果您有很多节点,因为它们最初都加载在(by.value)中,所以可以在代码中迭代。如果是几千,它工作得很好,速度也很快。

欢迎使用堆栈溢出!用实际数据示例、预期结果和实际结果更新您的问题会很有帮助。看看如何在这里创建一个最小的、完整的、可验证的示例:我想说的是,如何存储组的数量是一个问题。此查询涉及子查询,并且过于复杂,无法获得简单的结果。为什么不直接在数据库中存储用户所属的组数?示例用户->UID->GroupMemberCount?然后,您可以在用户加入/离开组时更新此值。这将使整个过程更容易。此外,snapshot.childrenCount会迭代所有子项,因此如果用户是许多组的成员,则可能效率不高。Thnx Giuseppe但我在问题中写了一个错误,我遗漏了一个嵌套的子项,结构是:[code]组-KwW2gHCbWzPCQpmbfhu--kxgqygqyg2cjkieln1addclose--ownerId:[code]不幸的是,这不起作用。您建议的查询将查询每个group1、group2的ownerId的直接子节点。如果查看结构group1和group2,它们没有ownerID子节点。它是子节点的子节点/groups/group1/ownerId,not/groups/ownerId.thnx Jay,你的方式是一个很好的方式,但目前我无法更改数据库结构,用我的代码(你可以看到的代码)我可以获得计数,如果我添加一个完整的,也许我只能读取最终计数。。。“你认为呢?”马可明白了。我用一个解决方案编辑了我的答案。它可以工作,但我不是特别喜欢它,因为我不喜欢给出一个可能会因为必须加载太多节点而失败的答案。早上我可能有另一个选择。Thnx@Jay它工作得很好,请告诉我你是否找到更好的解决方案!
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)")
})