【问题标题】:swift firebase nested children countswift firebase嵌套儿童计数
【发布时间】:2017-11-15 15:18:51
【问题描述】:
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)
            })
        }
    }
})

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

【问题讨论】:

  • 欢迎来到 Stack Overflow!使用实际数据示例、预期结果和实际结果更新您的问题会很有帮助。在此处了解如何制作最小、完整和可验证的示例:stackoverflow.com/help/mcve
  • 我想说的是如何存储组数是问题所在。该查询涉及子查询,过于复杂,无法得到简单的结果。为什么不直接在数据库中存储用户所属的组数?示例用户 -> UID -> GroupMemberCount?然后,您可以在用户加入/离开组时更新此值。这将使整个过程更容易。 snapshot.childrenCount 还会遍历所有子节点,因此如果用户是许多组的成员,它可能效率不高。

标签: swift firebase firebase-realtime-database


【解决方案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),所以它可以在代码中迭代。如果是几千的话,效果很好,速度也很快。

【讨论】:

  • thnx Jay,你的方法是一个好方法,但目前我无法更改数据库结构,使用我的代码(你可以看到的那个)我可以得到计数,如果我添加一个完整的也许我只能读到最后的计数......你觉得呢?
  • @Marco Gotcha。我用解决方案编辑了我的答案。它可以工作,但我不太喜欢它,因为我不喜欢给出一个可能由于必须加载太多节点而失败的答案。早上我可能有另一个选择。
  • Thnx @Jay 效果很好,如果您找到更好的解决方案,请告诉我!
【解决方案2】:

您可以通过执行.childAdded 类型的单个observe 来实现此步骤。子子节点上的 .childAdded(在您的示例中为 groups)就像迭代所有节点的 for 循环。

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

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

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

这是一个测试示例:

要优化性能,请记住在您的 Firebase 应用中添加 .indexOn 规则:

"groups" : {
  ".indexOn" : "ownerID"
}

希望对你有所帮助;)

【讨论】:

  • Thnx Giuseppe 但我在我的问题中写了一个错误,我错过了一个嵌套的孩子,结构是那个:[code] groups -KwW2gHCbWzPCQpmbfhu --Kxgqyhgqyg2CjKIEln1addclose ---ownerId:[code]
  • 不幸的是,这行不通。您建议的查询将查询每个 group1、group2 的 ownerId 的直接子节点。如果查看结构 group1 和 group2,它们没有 ownerID 子节点。它是子节点的子节点。 /groups/group1/ownerId,而不是 /groups/ownerId。
猜你喜欢
  • 1970-01-01
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多