如何在 Firebase JSON 树中表示双向关系?

How to represent a two ways relationship in a Firebase JSON tree?

警告:

我在用户和门钥匙之间建立了双向关系。我想了解:

这是一个很长的答案,因为您的问题实际上是关于 5 个不同的问题。

根节点是:myparentnodename

您的用户

  users
    uid_0
      name: "William"
      door_keys:
        key_0: true
        key_3: true
    uid_2
      name: "Leonard"
      door_keys:
        key_3: true
        key_5: true

和你的钥匙

  keys
    key_0
      uid_0: true
    key_3
      uid_0: true
      uid_2: true
    key_5
      uid_5: true

有了这个结构,所有的元素 'point' 都在彼此。

如果你查询 uid_0 你可以看到他们使用键 0 和 3

如果你查询 key_3 你可以看到他们属于用户 0 和 2

你的问题是

every time I would query the child node "users" I would get all the users back

这有点不完整。查询完成后,您通常会查询特定的内容。但是,对于 Firebase,有两种方法可以检索数据:观察节点和查询。

如果您想恢复用户节点中的所有用户,您可以通过 .Value(或 .ChildAdded 一次观察 1 个)观察该节点。

ref = myParentNodeName
let usersRef = myParentNodeName.childByAppendingPath("users")

usersRef.observeEventType(.Value, withBlock: { snapshot in

    //.Value can return multiple nodes within the snapshot so iterate over them
    for child in snapshot.children {
        let name = child.value.objectForKey("name") as! String
        print(name) //prints each users name
    }
})

请注意,上面将观察者附加到用户节点,因此该节点内的任何未来更改都会通知应用程序并将整个节点重新发送到应用程序

如果您只想要一个用户的信息,并且不想继续观察变化

ref = myParentNodeName
let usersRef = myParentNodeName.childByAppendingPath("users")
let thisUserRef = usersRef.childByAppendingPath("uid_2")
thisUserRef.observeSingleEventOfType(.Value, withBlock: { snapshot in

    let name = child.value.objectForKey("name") as! String
    print(name) //prints each users name
})

最后,查询属于 uid_0 的所有键(在这个例子中这有点多余,因为我们已经知道他们从他们的节点获得了哪些键)。如果 keys ref 还包含其他信息,例如门的名称、门所在的建筑物或门的位置,这将更合适并且需要不同的结构,因此假设是这种情况:

ref = myParentNodeName
let keysRef = myParentNodeName.childByAppendingPath("keys")

keysRef.queryOrderedByChild("uid_0").queryEqualToValue(true)
  .observeSingleEventOfType(.Value, withBlock: { snapshot in

        let doorLocation = child.value.objectForKey("door_location") as! String
        print(doorLocation) //prints each users name
})

请注意此代码是 Swift,因为问题中未指定平台。

另一个问题:

Can we do nested queries? e.g. combine the previous condition with some condition on the door keys so the JSON object returned is only relevant to the door-keys contained in the "user1" node?

我想你的意思是你可以查询 uid_2,看看他们有哪些键,然后加载这些特定键的信息。

是的!但是...(总有一个但是)

Firebase 是异步的,因此在嵌套查询时必须考虑到这一点,即您需要确保在获取更多数据之前返回所有数据。因此,例如,如果您想要 uid_2 关键数据,您可以在节点 uid_2 上观察 SingleEventOfType。然后您将拥有他们的密钥,然后可以在每个密钥上观察 SingleEventOfType。

从技术上讲,这可行,但随着异步数据四处传播,您最终可能会在其他代码上执行代码并在数据实际返回之前处理数据。

更好的选择(根据我的示例)是完全避免这种情况并查询键节点以获取 uid_2 的键。

附带说明一下,观察节点的开销比查询少很多,因此如果您想加载单个节点并且知道路径,请使用观察。