我有数据上传到我的数据库。我正在尝试实现搜索功能,该功能可以按名称搜索内容,如果找到该名称,则使用与该名称相对应的数据自动填充文本字段。因此,例如,如果我搜索“ Pepsi Max”,我想在数据库中找到pepsi max,然后显示价格/位置/价格等。
我目前有一个搜索功能,但是只搜索整个数据库并打印所有值。
func searchT() {
let pub = pubName.text
print(pub)
let databaseRef = Database.database().reference().child("Drinks")
let query = databaseRef.queryOrdered(byChild: "pub").queryStarting(atValue: pub).queryEnding(atValue: "\(String(describing: pub))\\uf8ff")
query.observeSingleEvent(of: .value) { (snapshot) in
guard snapshot.exists() != false else { return }
print(snapshot.value as Any)
DispatchQueue.main.async {
guard let dict = snapshot.value as? [String:Any] else {
print(snapshot)
return
}
let pubName = dict["pub"] as? String
let pubLocation = dict["location"] as? String
let price = dict["price"] as? String
let rating = dict["rating"] as? String
let comment = dict["comment"] as? String
self.pubName.text?.append(pubName!)
self.pubLocation.text?.append(pubLocation!)
self.price.text?.append(price!)
self.rating.text?.append(rating!)
self.comment.text?.append(comment!)
}
}
}
您会注意到,在此函数中,我正在搜索数据“ pubName”(我认为我在第一行中设置有误,但不确定如何更正)。
在将textViews设置为值的第一行时,此函数崩溃,因为“解包可选值时为零”如何通过pubName进行搜索,找到相应的值,然后将文本字段设置为db中与搜索值有关的其余数据。
谢谢,E
答案 0 :(得分:1)
1。实时数据库
由于您尚未包括数据库的结构,因此我假设您具有以下饮料的数据库结构:
Screenshot of my Realtime database for this answer
{
"Drinks" : {
"-LYiUHm4vtrB3LqCBxEc" : {
"location" : "toronto",
"name" : "pepsi max",
"price" : 13.5,
"rating" : 3.6
},
"-LYiUHm5Lgt3-LENTdBZ" : {
"location" : "new york",
"name" : "diet coke",
"price" : 15.45,
"rating" : 5
},
"-LYiUHm5Lgt3-LENTdB_" : {
"location" : "chicago",
"name" : "mountain dew",
"price" : 2,
"rating" : 2
},
"-LYiUHm5Lgt3-LENTdBa" : {
"location" : "vancouver",
"name" : "sprite",
"price" : 6.98,
"rating" : 4.5
}
}
}
2。 Swift 4.0
现在,要使用名称搜索任何饮料,请使用以下代码:
func search(drinkName: String) {
let databaseRef = Database.database().reference().child("Drinks")
let query = databaseRef.queryOrdered(byChild: "name").queryStarting(atValue: drinkName).queryEnding(atValue: "\(drinkName)\\uf8ff")
query.observeSingleEvent(of: .value) { (snapshot) in
guard snapshot.exists() != false else { return }
//print(snapshot.value)
DispatchQueue.main.async {
// Update TextFields here
}
}
}
以上查询中使用的\ uf8ff字符在Unicode范围内是一个很高的代码点。因为查询是在Unicode中大多数常规字符之后,所以该查询匹配所有以b开头的值。
来源:https://firebase.google.com/docs/database/rest/retrieve-data
注意:queryOrderedByChild()区分大小写。最好将所有字段都小写保存在数据库中,因为这样可以更轻松地查询数据。您始终可以在前端格式化字符串。
3。将“ .indexOn”添加到实时数据库的规则
为了使上面的查询起作用并获得更好的性能,您需要在要搜索的字段上设置索引。 您可以通过转到“规则”标签并添加如下所示的索引来完成此操作:
{
"rules": {
".read": true,
".write": true,
"Drinks": {
".indexOn": "name"
}
}
}
来源:More information on indexing data
更新后的问题的答案:
func searchT() {
// You must cast pub variable as String.
guard let pub: String = pubName.text else { return }
print(pub)
let databaseRef = Database.database().reference().child("Drinks")
let query = databaseRef.queryOrdered(byChild: "pub").queryStarting(atValue: pub).queryEnding(atValue: "\(String(describing: pub))\\uf8ff")
query.observeSingleEvent(of: .value) { (snapshot) in
guard snapshot.exists() != false else {
print("failing here")
return }
print(snapshot.value as Any)
DispatchQueue.main.async {
guard let dict = snapshot.value as? [String:Any] else {
print(snapshot)
return
}
let pubName = dict["pub"] as? String
let pubLocation = dict["location"] as? String
let price = dict["price"] as? String
let rating = dict["rating"] as? String
let comment = dict["comment"] as? String
}
}
}