我最近一直在开发应用程序,却偶然发现了另一个问题(那是程序员的生命,不是吗?)。作为记录,我正在使用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
}
我得到了六个值,但我希望有两个。我不知道为什么!预先感谢任何可以提供帮助的人。
答案 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和一个布尔值。
如果需要,我可以进一步更新。