Swift Get Specific Value from Firebase Database

How to get a specific value in firebase-realtime-database in swift 4.0

This is a standard Firebase Query.

To retrieve nodes that contain a child that has a certain value, we query the nodes for the node key in question and specify the value being looked for. They will be returned in a snapshot, and they can be more than one so we need to iterate over each of the returned snapshots.

let questionPostsRef = self.ref.child("questionPosts")
let query = questionPostsRef.queryOrdered(byChild: "trackId").queryEqual(toValue: "12345678")
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let childSnap = child as! DataSnapshot
let dict = childSnap.value as! [String: Any]
let cat = dict["category"] as! String
let name = dict["name"] as! String
print(childSnap.key, cat, name)
}
})

and the output would be (assume two were found)

-Lu9ma9jsd...  some category   some name
-K999a90k9... some category some name

This is covered in the Firebase guide: Work With Lists Of Data in the Sorting and Filtering section

Now, the question states

And I want find the trackId that has the same value as my variable and
then get that trackId

Of course if you know the trackId already you wouldn't need to fetch it since you already have it. My guess is that you want to return the nodes that match that track ID so you can get to the other data, so that's what the above code does. If you are asking something different, let me know.

EDIT: a followup for the OP. To configure Firebase, this is the typical design pattern within a view controller. From there, you can reference your Firebase throughout this class with self.ref (as in my answer above)

import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage

class ViewController: UIViewController {
var ref: DatabaseReference!

override func viewDidLoad() {
super.viewDidLoad()
self.ref = Database.database().reference()

Swift: Search for a specific value in Firebase Database & find all associated data

1. Realtime Database

Since you haven't included the structure of your database, I assume you have a database structure for drinks like below:

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

Now, to search any drink by name use below code:

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
}
}
}

The \uf8ff character used in the query above is a very high code point in the Unicode range. Because it is after most regular characters in Unicode, the query matches all values that start with a b.

Source: https://firebase.google.com/docs/database/rest/retrieve-data

Note: queryOrderedByChild() is case-sensitive. It is nice practice to save all fields lowercased in database as this makes it easier to query data. You can always format strings in front end.

3. Add ".indexOn" to Realtime Database's Rules

In order to above query to work and achieve better performance, you need to set the index on the field that you are going to search by.
You can do this by going to Rules tab and adding index like below:

{
"rules": {
".read": true,
".write": true,
"Drinks": {
".indexOn": "name"
}
}
}

Source: More information on indexing data

Updated Answer for your updated question:

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
}
}
}

Swift Get Specific Value From Firebase Database

At last I found a solution. If I declare a var and try to use later it returns nil, but if I try use snapshot.value as? String it's ok. Here is a example I did.

    ref: FIRDatabaseReference?
handle: FIRDatabaseHandle?

let user = FIRAuth.auth()?.currentUser

ref = FIRDatabase.database().reference()

handle = ref?.child("Kullanıcı").child((user?.uid)!).child("Yetki").observe(.value, with: { (snapshot) in

if let value = snapshot.value as? String{

if snapshot.value as? String == "admin"{
self.items.append("Soru Gönder")
self.self.tblView.reloadData()
}
}
})

Delete specific value from firebase database using swift

To write to or delete a node, you must specify its entire path. So to delete node 0 from your JSON, you'd do:

let usernameRef =  Database.database().reference().child("Candidate 1").child("alton").child("0");
usernameRef.removeValue();

Or a bit shorter:

let usernameRef =  Database.database().reference().child("Candidate 1/alton/0");
usernameRef.removeValue();

If you only know the name of the user you want to remove, you'll need to first look up its index/full path before you can remove it. If you have the data in your application already, you can do it in that code. Otherwise you may have to use a database query (specifically .queryOrderedByValue and .queryEqualToValue) to determine where the value exists in the database.

Also see: Delete a specific child node in Firebase swift


Once you remove a value from your JSON structure, Firebase may no longer recognize it as an array. For this reason it is highly recommended to not use arrays for the structure that you have. In fact, I'd model your data as a set, which in JSON would look like:

"alton": {
"Jake Jugg": true,
"Blake Wodruff": true,
"Alissa Sanchez": true
}

This would automatically:

  1. Prevent duplicates, as each name can by definition only appear once.
  2. Make removing a candidate by their name as easy as Database.database().reference().child("Candidate 1/alton/Jake Jugg").removeValue()

For more on this, also see my answer to Firebase query if child of child contains a value

How to get data of a specific value from firebase realtime data in swift?

queryEqualToValue is changed. By queryEqual

ref.child("POSTBY").queryEqual(toValue: regex.encodeEmails(email).observe(.value) { snapshot in
for child in snapshot.children {

}
}

Unable to fetch and print a single value from a Firebase Database with Swift 5 (iOS)

You're adding an observer to /Users/$uid/email, so the snapshot you get contains just the value of the email property. You are treating as a dictionary however, which explains why your code doesn't work.

To fix this, get the simple value from the

databaseReference.child("users").child((currentUser?.uid)!).child("email").observeSingleEvent(of: .value, with: { (snapshot) in

let valueRisk = snapshot.value as? String
print(valueRisk)

}) {(error) in
print(error.localizedDescription)
}

Reading child value from firebase database in swift

You need ( observe / observeSingleEvent is up to you according to the logic of your app )

REF_FEEDMESSAGES.child("\(key)/likes").observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value

}) { (error) in
print(error.localizedDescription)
}

Using this .value(forKey: "likes") as! String for sure will crash the app , as it's not a local dictionary to query it's data synchronously



Related Topics



Leave a reply



Submit