我试图查询我的Firebase数据库以查找特定姓名或电子邮件的用户。我已经找到了几个如何做到这一点的例子,所有这些例子似乎都比较容易理解,但没有一个像我预期的那样有效。
以下是我的json数据结构的示例。
{
"allUsers" : {
"uid0001" : {
"userInfo" : {
"email" : "firstName1.lastName1@email.com",
"firstName" : "firstName1",
"lastName" : "lastName1",
"uid" : "uid0001"
}
},
"uid0002" : {
"userInfo" : {
"email" : "firstName2.lastName2@email.com",
"firstName" : "firstName2",
"lastName" : "lastName2",
"uid" : "uid0002"
}
}
}
}
以下是我尝试查询数据库的示例函数
func performQuery(forName queryText:String)
{
let key = "firstName"
let ref1 = firebaseDatabaseManager.allUsersRef.queryOrdered(byChild: queryText)
let ref2 = firebaseDatabaseManager.allUsersRef.queryEqual(toValue: queryText, childKey: key)
//ref.observeSingleEvent(of: .childAdded, with: {(snapshot) in
ref1.observe(.childAdded, with: {(snapshot) in
let userId = snapshot.key
if let dictionary = snapshot.value as? [String: AnyObject]
{
if let userInfo = dictionary["userInfo"] as? [String:AnyObject]
{
if
let email = userInfo["email"] as? String,
let firstName = userInfo["firstName"] as? String,
let lastName = userInfo["lastName"] as? String
{
let user = User.init(withFirst: firstName, last: lastName, userEmail: email, uid: userId)
}
}
}
})
}
你可以在这里看到我有两个关于我如何构建ref的例子以及我如何观察引用的两个例子,尽管我已经尝试了我能想到的每一种可能的组合。
如果我使用ref.observe(.... 无论queryText是否实际存在,该块都将为该节点上的所有用户执行。 如果我使用ref.observeSingleEvent(of:.... 该块将为json结构中最顶层的用户执行。
最重要的是,我尝试了多种参考变化,但根本没有返回任何内容。
任何帮助都表示赞赏! 感谢
答案 0 :(得分:1)
您需要合并queryOrderedByChild:
和queryEqualToValue:
才能获得正确的结果:
let query = firebaseDatabaseManager.allUsersRef
.queryOrdered(byChild: "userInfo/" + key)
.queryEqual(toValue: queryText)
query.observe(.childAdded, ...
答案 1 :(得分:0)
尝试替换
let ref2 = firebaseDatabaseManager.allUsersRef.queryEqual(toValue: queryText, childKey: key)
带
let ref2 = ref1.queryEqual(toValue: queryText)
然后致电:
ref2.observe(.childAdded, with: {(snapshot) in
由于您现在不是在寻找某个用户,而是为所有用户寻找
答案 2 :(得分:0)
此问题是Firebase结构(不必要地)太深。
你拥有的是
"allUsers" : {
"uid0001" : {
"userInfo" : { <- This is the issue
"email" : "firstName1.lastName1@email.com",
"firstName" : "firstName1",
"lastName" : "lastName1",
"uid" : "uid0001"
}
},
应该(可能)
"allUsers" : {
"uid0001" : {
"email" : "firstName1.lastName1@email.com",
"firstName" : "firstName1",
"lastName" : "lastName1"
}
}
可能没有必要在uid0001节点内安装userInfo节点。
此外,您可能不需要存储在节点中的uid以及将其用作密钥 - 当返回节点时,您始终可以从snapshot.key获取每个用户的uid。
话虽如此,您实际上可以使用deep query执行此操作,但在这种情况下似乎并不需要它。 (请参阅Frank的答案,因为它是问题中发布的结构的正确解决方案)
并使用我建议的结构查询特定的名字
let fName = "firstName1"
let queryAllUsersRef = allUsersRef.queryOrdered(byChild: "firstName")
.queryEqual(toValue: fName)
//get all of the users with firstName1
queryRef.observeSingleEvent(of: .value, with: { snapshot in
//snapshot may return more than one user with that first name
// so iterate over the results
for snap in snapshot.children {
let userSnap = snap as! FIRDataSnapshot //each user is it's own snapshot
let userKey = commentSnap.key //the uid key of each user
let userDict = userSnap.value as! [String:AnyObject]
let email = userDict["email"] as! String
print("uid: \(userKey) has email: \(email)"
}
})