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

7

警告:

  • 这是一个练习,旨在更好地理解Firebase中JSON数据库设计
  • 它并不一定是真实的情况

我有两个用户和门钥匙之间的双向关系。我想了解:

  • 如何通过可视化方式表示此关系(我只能将其想象为两个独立的树
  • 在Firebase上如何使用它,usersdoor-keys是否都是父节点“myparentnodename”的子节点?
  • 如果我以这种方式建模数据库,那么每次查询子节点“users”时,我都会得到所有用户的返回。我错了吗?是否可能仅返回与特定用户匹配的数据?例如,获取“user = user1”的用户?我们可以进行嵌套查询吗?例如,将前面的条件与一些门钥匙的条件组合,以便返回的JSON对象仅与包含在“user1”节点中的门钥匙相关?

enter image description here

1个回答

11

作为你的问题涉及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

使用这种结构,所有元素都会“指向”彼此。

如果您查询uid_0,可以看到它们使用键0和3

如果您查询key_3,可以看到它们属于用户0和2

您的问题是:

每次查询子节点“users”时,我都会得到所有用户的返回

这有点不完整。当进行查询时,通常会查询特定内容。然而,在Firebase中,检索数据有两种方式:观察节点和查询。

如果您想获取users节点中的所有用户,请通过.Value(或.ChildAdded逐个)观察该节点。

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的所有键(在这个示例中有点冗余,因为我们已经知道它们的节点拥有哪些键)。如果键的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。

另一个问题:

我们可以进行嵌套查询吗?例如,将先前的条件与某些关于门钥匙的条件相结合,以便返回的JSON对象仅与包含在“user1”节点中的门钥匙相关?

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

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

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

从技术上讲,这将起作用,但是由于异步数据四处飞行,您可能会遇到代码践踏其他代码并在实际返回之前处理数据的情况。

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

顺便说一下,观察节点比查询的开销要小得多,因此如果要加载单个节点并且您知道路径,请使用observe。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接