从Firebase数据库中获取直接后代

时间:2019-07-25 23:50:11

标签: swift firebase firebase-realtime-database

我最近一直在开发应用程序,却偶然发现了另一个问题(那是程序员的生命,不是吗?)。作为记录,我正在使用Swift,XCode和Firebase的最新版本。我只想获取父母的直接后代(我的参考资料)。这是我的JSON树:

users
  family-name
    user-1      // I want this...
      pass: abc // but not this ...
    user-2      // ... and this
      pass: def // ... but not this
    events      // I skip this specifically in my code
      event-1
        a: a
        b: b
      event-2
        a: a
        b: b
      event-3
        a: a
        b: b

如树所示,我只想获取用户1,用户2和用户3。

我尝试使用普通查询,但没有用,而不是得到我想要的值,我也得到了子值。

let query = userRef.queryOrdered(byChild: "users")
query.observe(.value, with: { (snapshot) in
  for child in snapshot.children {
    let value = snapshot.value as? NSDictionary
    for anotherChild in value! {
      if "\(key)" == "events" {
        print("Let's skip that, since it's just the events sub-tree!")
      } else {
        // my work goes here
      }

我得到了六个值,但我希望有两个。我不知道为什么!预先感谢任何可以提供帮助的人。

2 个答案:

答案 0 :(得分:1)

实时数据库查询是“深度”的,因为对节点的请求始终重试该节点下的所有子级。使用客户端库时,没有“浅”查询,也没有办法从节点中排除子级。如果您想要特定的孩子,而不是他们的兄弟姐妹,则必须分别要求他们。

答案 1 :(得分:1)

我将提供问题的具体答案,并建议对结构进行更改并给出答案。

首先,以任何方式读取Firebase节点时,它将加载节点密钥(这是您要执行的操作)以及子数据。这就是Firebase的工作方式。只要子数据不广泛,就非常简单。

在这里,我们加载用户家庭节点,该节点将加载家庭中的所有数据,然后分配子快照数据,这些数据是关键的:将值对分配给字典。从那里我们创建一个包含这些键(用户1,用户2等)的数组,然后遍历它们,打印所有非“事件”的键

func printUids() {
    let familyRef = self.ref.child("users").child("family-name")
    familyRef.observeSingleEvent(of: .value, with: { snapshot in
        let dict = snapshot.value as! [String: Any]
        let allKeys = dict.keys
        for key in allKeys {
            if key != "events" {
                print(key)
            }
        }
    })
}

但是,在这些情况下,对数据进行非规范化可以减少丢失的数据。我不知道确切的用例,但让我提出一个修改后的结构,其中将所有用户存储在一个用户节点中,然后将家庭数据存储在另一个节点中。

users
   uid_0
      name: "uid_0 users name"
      fav_food: "pizza"
   uid_1
      name: "uid_1 users name"
      fav_food: "pizza"

,然后是包含家庭名称,家庭事件和属于该家庭的家庭成员(用户)的家庭数据,由用户uid引用

families
    family_id_0
       family_name = "some family name"
       family_users
          uid_0: true
          uid_1: true
       family_events
          event_0
              event_desc: "family reunion"
              event_data: "some date"

假设我们想知道哪些家庭成员(用户)属于family_id_0。以下代码读取该家族的特定节点,并打印出家族成员(用户)

func printFamilyUsers() {
    let familiesRef = self.ref.child("families")
    let whichFamilyRef = familiesRef.child("family_id_0")
    let familyUsersRef = whichFamilyRef.child("family_users")

    familyUsersRef.observeSingleEvent(of: .value, with: { snapshot in
        let theUsers = snapshot.children.allObjects as! [DataSnapshot]
        theUsers.forEach { print($0.key) }
    })
}

这里的优点是通过参考存储用户,因此在加载用户时,数据量非常少;只是一个uid和一个布尔值。

如果需要,我可以进一步更新。