Searching through child values Firebase / Swift - ios

My database has values sorted like this :
Users
UID
Username
Email
I'm wanting to implement a friend adding system where you search for either a username or email and it lets you add the person.
I'm able to locate users by using
REF_USERS.queryOrdered(byChild: "displayname").queryEqual(toValue: input).observeSingleEvent(of: .value) { (snapshot: FIRDataSnapshot) in {
print(snapshot.value)
}
With that I get the user's entire dictionary, but I'm having an issue grabbing the UID.
snapshot.key gives me "Users".
How can I grab the UID value out of the dictionary after finding the user's dictionary with either their username/email?

Try this...
Assume a structure (this is Swift 2, Firebase 2)
users
uid_0
email: "someuser#thing.com"
displayName: "some display name"
and we want to get uid_0's info
let displayName = "some display name"
usersRef.queryOrdered(byChild: "displayName").queryEqual(toValue: displayName)
.observeSingleEvent(of: .childAdded) { (snapshot: FIRDataSnapshot) in {
let dict = snapshot?.value as! [String: AnyObject]
let email = dict["email"]
let displayName = dict["displayName"]
print(email!)
print(displayName!)
let key = snapshot?.key
print(key!)
}
A couple things to note
The 'dict' variable is being told it's being assigned a dictionary of type [String: Anyobject].
Any Object could well, be any object. A String, another dictionary, an int. So you need to ensure you code can handle whatever the object is
The snapshot key in this case is the snapshot of this user, and the key must be the parent node, which in this case is uid_0. So the output is
someuser#thing.com
some display name
uid_0
EDIT:
Updated for Firebase 4, Swift 4 and handle the case where multiple children are returned
let usersRef = self.ref.child("users")
let input = "some display name"
let query = usersRef.queryOrdered(byChild: "displayName").queryEqual(toValue: input)
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let email = dict["email"] as! String
let displayName = dict["displayName"] as! String
print(email)
print(displayName)
let key = snapshot.key
print(key)
}
})

When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
let query = REF_USERS.queryOrdered(byChild: "displayname").queryEqual(toValue: input)
query.observeSingleEvent(of: .value) { (snapshot: FIRDataSnapshot) in {
for child in snapshot.children {
print(child.key)
}
}
Also see:
Firebase snapshot.key not returning actual key?
Firebase access keys in queryOrderBy
Firebase access keys in queryOrderBy
Firebase getting data in order

Related

I cannot retrieve data from Firebase database

I setup Firebase database like this:
dataS
- LjYal4ijEdjfafe
- email: "abc#xxx.org"
- firstname: "aa"
- lastname: "bb"
And I cannot retrieve data "lastname", it always return nil.
let ref = Database.database().reference()
ref.queryOrdered(byChild: "email").queryEqual(toValue: email1).observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists() {
print("cannot find in firebase")
return
}
let value1 = snapshot.value as? NSDictionary
let lastnameP = value1?["lastname"] as? String ?? ""
print(lastnameP)
There are a few issues with the code.
The first is when observing by .value, all of the matches will be returned whether it be 1 or 1000 so that returned DataSnapshot will need to be iterated over to access the child data, even if there's 1. If using .childAdded, it will return one at a time in the snapshot if using .observe, and only the first using .childAdded.
Second thing is the reference is pointing at the root reference. It appears dataS may be a child of the root
root_firebase
dataS
uid
email
firstname
lastname
if not, then keep in mind this code matches that structure.
Last thing is to make it more Swifty and use modern function calls and add a little error checking in case the lastname node is not found with the nodes being read.
let email1 = "email to query for"
let ref = Database.database().reference()
let nodeToQueryRef = ref.child("dataS")
nodeToQueryRef.queryOrdered(byChild: "email")
.queryEqual(toValue: email1)
.observeSingleEvent(of: .value, with: { snapshot in
if snapshot.exists() == false {
print("cannot find in firebase")
return
}
let returnedSnapshotArray = snapshot.children.allObjects as! [DataSnapshot]
for snap in returnedSnapshotArray {
let key = snap.key
let lastName = snap.childSnapshot(forPath: "lastname").value as? String ?? "No Last Name"
print(key, lastName)
}
})

Firebase query results are mistaken

This is my database design.
foodie-ab2b4{
Foods{
0{
FoodName: "Baked Beans In Tomato Sauce"
FoodRecipe:
FoodUri:
Image:
}
1{
FoodName: "Another bean | Bubbling Bacon Butter Beans recipes"
FoodRecipe:
FoodUri:
Image:
}
}
}
I'm working on an ios project and this is how my firebase json structured.
let ref = Database.database().reference()
func searchFoodByName(FoodName: String){
let foodsRef = ref.child("Foods")
let input = FoodName
let query = foodsRef.child(key).queryOrdered(byChild: "FoodName").queryEnding(atValue: input)
query.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot)
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let fName = dict["FoodName"] as! String
let fIngredients = dict["Ingredients"] as! [String]
print(fName)
print(fIngredients)
let key = snapshot.key
print(key)
}
})
}
I'm trying to filter my food objects by their names. I have 10 objects in my database. In most cases this search return true objects. But there is one example i can not solve.
When i query the "tomato" word i need to get 1 object. But there is two. Although there is no tomato word in my second object.
The two object is in my json file.
If it is necessary i can upload my whole JSON file to here.
You seem to assume that Firebase can filter based on strings that contain a value, but it can't. See Firebase query - Find item with child that contains string (and the many links from there).
What Firebase can do is search for string values that start with a certain value. You do that by using a combination of queryStarting(atValue:) and queryEnding(atValue:):
let query = foodsRef
.queryOrdered(byChild: "FoodName")
.queryStarting(atValue: input)
.queryEnding(atValue: input+"\\uf8ff")
If you use this query, and input is ``Baked`, it will only match the first food from your JSON.

Getting all data in a Firebase column

I created JSON database tree and I can read specific values with these codes. I can see on table view "Albert Einstein"
ref.child("Personel").child("Name").observeSingleEvent(of: .value, with: { (snapshot) in
if let item = snapshot.value as? String{
self.myList.append(item)
self.LessonsTableView.reloadData()
}
})
But, I want to see which categories under Personal column? Like this,
Is there any way to get or learn which columns are under "Personal"
Table view output must be -> Age, Name, Photo
You can iterate over the snapshot, get it's children and then those childrens keys
Say you have a users node with a user
users
user_0
fav_game: "WoW"
name: "Leroy"
then to get the keys of name: and fav_game:
let userRef = self.ref.child("users").child("user_0")
userRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let key = snap.key
print(key)
}
})
prints
fav_game
name
An important note is
for child in snapshot.children
because that will keep the data (keys in this case) in order. If the snapshot is dumped into a dictionary it looses order.
If you loop through snapshot.value you should be able to get the keys from the database.
In JavaScript it would be something like:
ref.child("Personel").child("Name").observeSingleEvent(of: .value, with: { (snapshot) in
if let item = snapshot.value as? String{
self.myList.append(item)
self.LessonsTableView.reloadData()
}
var vals = snapshot.val();
for(var property in vals) {
console.log(property); // property has those values in it
}
})
This is one way:
ref.child("Personel").observeSingleEvent(of: .value, with: { (snapshot) in
self.myList.append(snapshot.childSnapshot(forPath: "Age").value)
self.myList.append(snapshot.childSnapshot(forPath: "Name").value)
self.myList.append(snapshot.childSnapshot(forPath: "Photo").value)
self.LessonsTableView.reloadData()
})

Firebase query of table

I have a Firebase table called Users where I store user objects of form
"users": {
"user1": {
"name": "username",
"id": "userID",
},
}
How can I create a proper query to get all users with 'name'.
I tried this, but this returns a null snapshot:
let ref = self.getDatabaseInstanceWith(child: FirebaseIdentifiers.tableUsers)
ref.queryOrdered(byChild: "name")
.queryEqual(toValue: "username")
.observe(.value, with: { snapshot in
}
A Firebase query to retrieve the uid's for users named John
let queryRef = usersRef.queryOrdered(byChild: "name").queryEqual(toValue: "John")
//get all of the comments tied to this post
queryRef.observeSingleEvent(of: .value, with: { snapshot in
for snap in snapshot.children {
let userSnap = snap as! FIRDataSnapshot
let userDict = userSnap as! [String:AnyObject]
let uid = userSnap.key
let name = userDict["name"] as! String
print("key = \(uid)") //prints the johns uids
}
})
However....
The above code requires a slightly different Firebase Structure.
A typical Firebase design pattern is to use the uid of the user as the key to the user node
users
uid
name: "some name"
location: "somewhere"
If you want to use your structure, then the id would just be retrieved as a child node instead of the userSnap.key
let name = userDict["name"]
let uid = userDict["id"]

How to retrieve objects from firebase by key value

I'm new to firebase and I have such structure of my firebase project
I want to get all objects, that "Interested" value is equal to "men"
I wrote such code, to get all object sorted by interes value:
let thisUserRef = URL_BASE.childByAppendingPath("profile")
thisUserRef.queryOrderedByChild("Interest")
.observeEventType(.Value, withBlock: { snapshot in
if let UserInterest = snapshot.value!["Interest"] as? String {
print (snapshot.key)
}
}
But I receive nil.
you need to loop through all the key-value profiles
if let allProfiles = snapshot.value as? [String:AnyObject] {
for (_,profile) in allProfiles {
print(profile);
let userInterest = profile["Interest"]
}
}
Here _ is the key that is in the format KYXA-random string and profile will be the element for that key.
Edit:
There is querying for child values as per the docs.
Try thisUserRef.queryOrderedByChild("Interest").equalTo("men") and then using the inner loop that i specified in the answer
This is a basic query in Firebase. (Updated for Swift 3, Firebase 4)
let profileRef = self.ref.child("profile")
profileRef.queryOrdered(byChild: "Interest").queryEqual(toValue: "men")
profileRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let dict = child as! [String: Any]
let name = dict["Name"] as! String
print(name)
}
})
The legacy documentation from Firebase really outlines how to work with queries: find it here
Legacy Firebase Queries
The new documentation is pretty thin.
Oh, just to point out the variable; thisUserNode should probably be profileRef as that's what you are actually query'ing.

Resources