如何在 Firebase JSON 树中表示双向关系?
How to represent a two ways relationship in a Firebase JSON tree?
警告:
- 这是一个练习,可以更好地理解 JSON Firebase
中的数据库设计
- 不一定现实
我在用户和门钥匙之间建立了双向关系。我想了解:
- 如何直观地表示这种关系(我只能把它想象成两棵独立的树)
- 这在 Firebase 上如何工作,users 和 door-keys 都是父节点 "myparentnodename" 的子节点吗?
- 如果我以这种方式对数据库建模,感觉效率非常低,因为每次我查询子节点时 "users" 我都会找回所有用户。还是我错了?是否可以只取回与特定用户匹配的数据?例如。让用户在哪里 "user = user1"?我们可以做嵌套查询吗?例如将先前的条件与门钥匙上的某些条件相结合,因此返回的 JSON 对象仅与 "user1" 节点中包含的门钥匙相关?
这是一个很长的答案,因为您的问题实际上是关于 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 的键。
附带说明一下,观察节点的开销比查询少很多,因此如果您想加载单个节点并且知道路径,请使用观察。
警告:
- 这是一个练习,可以更好地理解 JSON Firebase 中的数据库设计
- 不一定现实
我在用户和门钥匙之间建立了双向关系。我想了解:
- 如何直观地表示这种关系(我只能把它想象成两棵独立的树)
- 这在 Firebase 上如何工作,users 和 door-keys 都是父节点 "myparentnodename" 的子节点吗?
- 如果我以这种方式对数据库建模,感觉效率非常低,因为每次我查询子节点时 "users" 我都会找回所有用户。还是我错了?是否可以只取回与特定用户匹配的数据?例如。让用户在哪里 "user = user1"?我们可以做嵌套查询吗?例如将先前的条件与门钥匙上的某些条件相结合,因此返回的 JSON 对象仅与 "user1" 节点中包含的门钥匙相关?
这是一个很长的答案,因为您的问题实际上是关于 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 的键。
附带说明一下,观察节点的开销比查询少很多,因此如果您想加载单个节点并且知道路径,请使用观察。