【问题标题】:Fetch direct descendants from Firebase Database从 Firebase 数据库中获取直接后代
【发布时间】:2019-07-25 23:50:11
【问题描述】:

我最近一直在开发一个应用程序,但偶然发现了另一个问题(这就是程序员的生活,不是吗?)。作为记录,我正在使用最新版本的 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

如图树所示,我只想获取 user-1、user-2 和 user-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
      }

我收到六个值返回给我,但我希望有两个。我不知道为什么!提前感谢任何可以提供帮助的人。

【问题讨论】:

  • 请注意,正如 Doug 在回答中所述,我不知道“浅”或直接后代值是什么。
  • 所以你想要family-name下的所有子键?所以您希望 Firebase 返回字符串 *user-1、user-2、events' 等?如果是这样,您将需要重新考虑您的结构,但其余的很容易。此外,当您读取节点时,它将读取节点密钥以及节点内的其余数据 - 这就是 Firebase 的工作方式。但是,这可能适用于您的情况,只需稍作代码更改或 Firebase 结构更改即可轻松完成。你能澄清一下吗?
  • @jay 是的,我想接收用户 1、用户 2 和事件。我需要什么样的代码更改?

标签: swift firebase firebase-realtime-database


【解决方案1】:

我将提供问题的具体答案以及对结构的建议更改以及答案。

首先,当以任何方式读取 Firebase 节点时,它将加载节点键(这是您所追求的)以及子数据。这就是 Firebase 的工作方式。只要子数据不广泛,就很简单。

这里我们加载用户家庭节点,该节点加载家庭内的所有数据,然后将子快照数据(键:值对)分配给字典。从那里我们创建一个包含这些键(user-1、user-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 和一个 bool。

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

【讨论】:

  • 谢谢,这有帮助!
【解决方案2】:

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

【讨论】:

  • 问题是,我不知道“浅”值是什么,因此无法进行单独的查询......但无论如何,谢谢。
  • 如果您无法识别数据库中某个节点的唯一完整路径,那么您将无法仅查询该节点。没有通配符或子字符串搜索节点名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 2012-12-29
  • 2020-12-22
  • 1970-01-01
  • 2019-01-17
相关资源
最近更新 更多