Firebase query of table - ios

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"]

Related

What could cause a Swift/Firebase app to act up the first time it is installed and never again?

What doesn't work the first time?:
The order in which database entries that I fetch displays
I am running this
1st part In ViewDiDLoad
let thisUserRef = Database.database().reference().child("users").child(uid)
let myPeopleRef = thisUserRef.child("likers")
myPeopleRef.queryLimited(toLast: 30).observeSingleEvent(of: .value, with: { snapshot in
let userArray = snapshot.children.allObjects as! [DataSnapshot]
for person in userArray.reversed() where uid == Auth.auth().currentUser?.uid {
let personUid = person.value as! String
self.printPersonInfo(uid: personUid) //// this calls a DispatchQueue.main.async that appends the data in the array and reloads
}
})
func printPersonInfo(uid: String) {
print(uid)
let usersRef = Database.database().reference().child("users")
let thisUser = usersRef.child(uid)
thisUser.observeSingleEvent(of: .value, with: { snapshot in
let xx = snapshot.childSnapshot(forPath: "xx").value as? String ?? "No Entry"
let yy = snapshot.childSnapshot(forPath: "yy").value as? String ?? "No Entry"
let rr = snapshot.childSnapshot(forPath: "rr").value as? String ?? "No Entry"
let zz = snapshot.childSnapshot(forPath: "zz").value as? String ?? "No Entry"
let ll = snapshot.childSnapshot(forPath: "ll").value as? String ?? "No Entry"
let p = Usery(xx: xx, yy: yy, rr: rr, zz: zz, ll: ll)
self.person.append(p)
print(self.person, "person")
self.table.reloadData()
})
}
//////this gets the various data elements of the users that get displayed.
///////So to summarize, the query determines which users get displayed. This func determined which data of those users gets displayed.
Example of database entires of last 30
user K
user B
user F
user G
user K
user B
user K
.....
The only time this doesn't work is if you install the app clean for the first time. Then the order in which it displays is
user K
user K
user B
user B
user F
user G
JSON
users
uid
likers
chailbyAutoID: uid1
chailbyAutoID: uid2
One possible solution is to use DispatchGroups to control the loading of the data, which therefore would control the sequence in which a class var array is populated.
In this example, we'll read all of the users uids from a users node and populate an array. It would look like this
users
uid_0
name: "Wilbur"
uid_1:
name: "Orville"
We'll then go back and re-read additional user data from that node, using array.reversed() so they populate a result array in reversed order. We'll need a class to store each user data and then a class array to store all of the users are they are read in. Here's the class vars
struct PersonClass {
var uid = ""
var name = ""
}
var personArray = [PersonClass]()
and the code to populate them in reverse order
func readUserDataUsingDispatch() {
let ref = self.ref.child("users") //self.ref points to my firebase
ref.observeSingleEvent(of: .value, with: { snapshot in
//this just builds and array of user id's - we'll iterate through them to read the rest of the data
let idArray = snapshot.children.allObjects as! [DataSnapshot]
var allKeys = [String]()
for userSnap in idArray {
allKeys.append( userSnap.key ) //[uid_0, uid_1] etc
}
let group = DispatchGroup()
for uid in allKeys.reversed() {
group.enter()
let thisUser = ref.child(uid)
thisUser.observeSingleEvent(of: .value, with: { userSnapshot in
let name = userSnapshot.childSnapshot(forPath: "name").value as! String
let person = PersonClass(uid: uid, name: name)
self.personArray.append(person)
print("added uid")
group.leave()
})
}
group.notify(queue: .main) {
print("done")
}
})
}
when you run the code this is the output, indicating the data is loaded
added uid
added uid
done
and then when printing the class var personArray it's the users in reverse order.
uid_1 Orville
uid_0 Wilbur

get certain node from list of children firebase ios

Im trying to retrieve a specific node in all my children and want to collect all the "role" in every child under "Users"
Here is the database setup:
Users:
25TWFD7SLmQ3onRUdffvfx6Nfmw1:
role: "officer"
9OwM6FIPZgOKu3zzVYSrkPWR0Ij2
role: "advisor"
How can I retrieve all of the "role" nodes?
here you can get the particular node "role".
//To get the all record
let ref = Database.database().reference()
ref.child("Users").childByAutoId().queryOrdered(byChild: "role").observeSingleEvent(of: .value) { (snapshot) in
//To check the data
guard let userDict = snapshot.value as? [String:Any] else {
return
}
let keyArray = [String] (userDict.keys)
for key in keyArray {
if var dataDict = userDict[key] as? [String:Any] {
self.userRoleArray.append(dataDict)
}
}
}
Hopefully this will work for you.
happy coding...

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

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

Searching through child values Firebase / Swift

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

Resources