How to get the value of a key in firebase - iOS - ios

so this is an image of my JSON tree:
my JSON TREE
Question:
I wanted to know how can I check if the username, let's say, sean exists in the usernames. I currently have no idea on how to implement this.
What I've tried:
The key of usernames child is "theUsernameOf-userUID", and that causes the problem as userUID is dynamic and different from each user (from firebase auth), therefore I can't use:
.queryOrderedByChild("theUsernameOf-userUID").queryEqual(toValue: self.usernameTextBox.text!)
The key of usernames child can't be static like theUsername as it would only be able to have 1 value / not able to generate more node.
Thank you so much, sorry if I didn't explain clearly enough.

I would like to modify your DB structure as current one is not the correct to perform this query.
It should be like below:
Always use auto incremented keys for queries. Here usernames -> autoGeneratedKey -> yourData (Dictionary - Key-Value pair) Now you can easily check the existence of any key.
let ref = defaultDB.reference.child("usernames")
ref.queryOrdered(byChild: "username").queryEqual(toValue: "sean").observeSingleEvent(of: DataEventType.value) { (snapshot) in
if snapshot.exists() {
print("exists")
}
else {
print("doesn't exist")
}
}
Output: exists
This is the correct way to do so. Just checking for snapshot.exists() will do the job for you.

When you observe any reference in firebase, you get a DataSnapshot in return. The snapshot has a children enumerator property on which you can enumerate each child. Each of the child will be another DataSnapshot. Now, each snapshot has key and value. You want the user name? It's in the value property:
let databaseRef = Database.database().reference(withPath: "usernames")
databaseRef.observe(.value) { (snapshot) in
snapshot.children.forEach({ (child) in
if let child = child as? DataSnapshot, let value = child.value {
print(value) //"Sean", "Yuh"
// here you can check for your desired user
}
})
}

Here is how you can do it
Set the database reference to the usernames node. For example db.ref.child("usernames")
Now parse the snapshot using for loop
let usernames = snapshot.value as! NSDictionary
Now the for loop
for username in usernames{
if username.value == "Sean"{
// do whatever you want here
}
}

You could also:
Make a firebase call to usernames and make that:
let usernames = snapshot.value as? [String: AnyObject],
then all you have to do is something like
if let keyExists = usernames[YOURUSERNAMECHECKSTRING] {
//It's true
}
Just another way of looking at it.

Try This code will Help you you dont need to change your firebase structure
In Swift
Database.database().reference(withPath: "users").queryOrdered(byChild: "usernames").queryEqual(toValue: "yourUserName").observe(.value)
{ (snapshot:DataSnapshot) in
if snapshot.valueInExportFormat() is NSDictionary
{
// User is exits
}
else
{
}
}
In Objective c
[[[[[FIRDatabase database] referenceWithPath:#"users"] queryOrderedByChild:#"usernames"] queryEqualToValue:#"your User Name"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot)
{
if ([snapshot.valueInExportFormat isKindOfClass:[NSDictionary class]])
{
// User is exits
}
else
{
}
}];

Related

get a KEY, given a value, from Firebase in Swift

Have a registry of users, and we would like to input an email address, then return the UID.
Is there a way to do this in swift?
We would like the function to return this.
like we'd input user#user.com into the function and it will return gSVeU6....
Any tips and suggestions are really appreciated man.
Here is what the firebase JSON tree looks like
func findFriendsUIDFromFirebase(selectedFriendsEmail: String) {
print("Hey from findFriendsUIDFromFirebase called")
fir.child("registeredUsersOnPlatform").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
guard let allTheUsers = snapshot.value as? [String:String] else {
print("Something is wrong with this snapshot")
return
}
if let selectedUserUIDFromFirebase = allTheUsers.someKey(forValue: selectedFriendsEmail) {
//DO STUFF
basically in this way we download everything locally then loop through the dictionary, but am looking for a better way, one that doesn't involving downloading the whole thing. Maybe something with a .equals()?
At the same time, for some reason when printing the dictionary, it seems to be stuck at 100 key-value pairs. when there are like 300ish pairs on the actual table. It's some clipping somewhere.
You would need to perform a Firebase query for the specific value you are looking for:
let queryEmail = "Userone#user.com"
fir.child("registeredUsersOnPlatform").queryOrderedByValue().queryEqual(toValue: queryEmail).observeSingleEvent(of: .value) { (querySnapshot) in
for result in querySnapshot.children {
let resultSnapshot = result as! DataSnapshot
print (resultSnapshot.key)
}
}
You can also limit the amount of query results you would like with .queryLimited(toFirst: x)
If you want to get Key when create User in firebase you can get them in user callBack data like:
Auth.auth().createUser(withEmail: email, password: pwd) { (user, _) in
print(user?.uid)
}
Else if you want to get key from value in normal lists data so that use queryEqualToValue then print snapshot's child key

Swift: how to retrieve data from firebase?

My structure in firebase is as follows:
app name
user ID
wins = 7
losses = 8
and my code to read the wins child node
ref = Database.database().reference().child(passUserID)
ref?.child("wins").observe(.childAdded, with: { (snapshot) in
//Convert the info of the data into a string variable
let getData = snapshot.value as? String
print(getData)
})
But it prints nothing.
To read data from Firebase you attach a listener to a path which is what creates a FIRDatabase reference. A FIRDatabaseReference represents a particular location in your Firebase Database where there is a key-value pair list of children. So in your case, you have created a Firebase reference to the key "wins" which only points to a value and not a key-value pair. Your reference was valid up to this point:
ref = Database.database().reference().child(passUserID)
//did you mean FIRDatabase and not Database??
This FIRDatabaseReference points to the key passUserID which has a key-value pair list of children ["wins":"7"] and ["losses":"8"] (NOTE: a key is always a string). So from your FIRDatabase reference, you create your observer as follows and read the value of "wins":
ref?.observe(.childAdded, with: { (snapshot) in
//Convert the info of the data into a string variable
if let getData = snapshot.value as? [String:Any] {
print(getData)
let wins = getData["wins"] as? String
print("\(wins)")
}
})
The Child added event will fire off once per existing piece of data, the snapshot value will be an individual record rather than the entire list like you would get with the value event. As more items come in, this event will fire off with each item. So if "losses" is the first record you might not get the value of "wins". Is this what you are trying to achieve? If what you really wanted to know is the value of "wins" at that particular location and to know if this value has ever changed you should use the .value observer as follows:
ref?.observe(.value, with: { (snapshot) in
//Convert the info of the data into a string variable
if let getData = snapshot.value as? [String:Any] {
let wins = getData["wins"] as? String
print("\(wins)") //check the value of wins is correct
}
})
Or if you just wanted to get the know the value of wins just once and you are not worried about knowing if there any changes to it, use the "observeSingleEvent" instead of "observe".
EDIT
I saw your image and now realize you might also have a problem with your reference. Your ref should actually be something like:
ref = FIRDatabase.database().reference().child("game-").child(passUserID)
You have obscured what "game" is but a valid reference to "wins" will include it.
SECOND EDIT
I will add the following so you can properly debug the problem. Use this pattern to observe the value and see if you get an error returned and what is says:
ref.observe(.value, with: { (snapshot) in
print(snapshot)
}, withCancel: { (error) in
print(error.localizedDescription)
})
Normally it will give you an error if you cannot access that Firebase location because of a database rule. It will also be a good idea to see if print(snapshot) returns anything as above.
You need this:
ref.child("YOUR_TOP_MOST_KEY").observe(.childAdded, with: { (snapshot) in
let keySnapshot = snapshot.key
//print(keySnapshot)
self.ref.child(keySnapshot).observe(.value, with: { (snapshot2) in
//print(snapshot2)
}) { (error) in
print("error###\(error)")
}
})

Firebase Sort array of class by value

I'm using Firebase. In my app, I get a child value by passing in a bottleID and get the details for that value from the snapshot. I then assign the details to an object of MyCollection_Class and add it to an array. After getting every single bottle value, I want to sort that array using the created_at tag before reloading the table view. Please advise me on how to sort the array of objects by a specific instance variable.
let Collection = MyCollection_Class()
FireBaseConstants.AUCTIONS_REF.child(bottleID).observeSingleEvent(of: .value, with: { (snap) in
if !(snap.value is NSNull) {
Collection.id = bottle_dict["id"] as? String
Collection.item_number = bottle_dict["item_number"] as? Int
Collection.created_at = bottle_dict["created_at"] as? String
if !(self.MyCollectionsIDArr.contains(Collection.id! as String)) {
self.MyCollectionsArr.append(Collection)
self.MyCollectionsIDArr.append(Collection.id!)
// I want to sort the MyCollectionsArr using created_at here
self.tbl_Latest.reloadData()
}
}
})
You can just retrieve the data already sorted from Firebase by using
queryOrderedByChild.
An example would be:
ref.child(bottleID).queryOrderedByChild("created_at").queryEqualToValue(0).observe SingleEventOfType(.Value, withBlock: { snap in
print("snap \(snap)")
expectation.fulfill()
})

How to update value in Firebase with childByAutoId?

When I create objects in Firebase, I use childByAutoId. How can I update these specific objects later? I'm having trouble obtaining the value of the key Firebase automatically updates. Snapshot.key just returns "users". Here's my JSON structure:
{
"users" : {
"-KQaU9lVcUYzIo52LgmN" : {
"device" : "e456f740-023e-440a"
"name: "Test"
}
},
How can I get the -KQaU9lVcUYzIo52LgmN key? I want to update the device child. Here's what I have so far. It currently creates a completely separate snapshot with a single child.
self.rootRef.child("users").queryOrdered(byChild: "name").queryEqual(toValue: self.currentUser).observeSingleEvent(of: .value, with: { (snapshot) in
let key = self.rootRef.child("users").childByAutoId().key
let childValues = ["device": device]
self.rootRef.child("users").child(key).updateChildValues(childValues)
Edit: device is a string set further up in the code. Not defined in this scope (to make it easier to read for this question).
When you get Snapshot.key, it returns "users" because that is the overall key for your snapshot. Everything inside of "users" in your snapshot is considered the value.
You need to iterate over the child layers to dig down to "device".
Try this:
rootRef.child("users").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if let result = snapshot.children.allObjects as? [FIRDataSnapshot] {
for child in result {
var userKey = child.key as! String
if(userKey == userKeyYouWantToUpdateDeviceFor){
rootRef.child("users").child(userKey).child("device").setValue(device)
}
}
}
})
This code will do the following:
Gets snapshot of your reference (the key for that would be
'users').
Gets all the children (your user keys) and assigns them as another
snapshot to 'result'.
Checks each key one at a time until it finds the key you want (for
example, if you look for user with the key "-KQaU9lVcUYzIo52LgmN",
it will find it on the first iteration in your example code you
posted).
Once it finds that key, it sets the value for the device inside that
key with the line
rootRef.child("users").child(userKey).child("device").setValue(device).
Of course, you will need to store all your user keys when you make them. You can maybe use SharedPreferences on the device for this, but if it gets cleared for any reason then that data will just be sitting there. You could also store it on internal storage for your app, but SharedPreferences is what I would use.
Hope this helps!
snapshot has a property key which is
The key of the location that generated this FIRDataSnapshot.
And as you can see you are getting one (snapshot) by calling observeSingleEvent(of: .value, with: { (snapshot)...
so instead of let key = self.rootRef.child("users").childByAutoId().key
try to call let key = snapshot.key
childByAutoId().key always generates new unique key based on timestamp, that's why you are creating new child, not updating the one you want
Hope that works
I adapted Ryan's answer to my own issue (kinda similar) and figured out a way to update your device ID directly without needed to know/store the AutoID key generated by Firebase :
reference = Database.database().reference().child("users")
reference.observeSingleEvent(of: .value, with: { (snapshot) in
if let result = snapshot.children.allObjects as? [DataSnapshot] {
for child in result {
if child.childSnapshot(forPath: "device").value as? String == self.yourDeviceIDVariable {
print("### Device exists in Firebase at key = \(child.key)")
let childKey = child.key
self.reference.child(childKey).child("device").setValue(yourNewDeviceID)
}
}
}
})

Firebase data comparison swift

hi I'm new to swift and i'm using firebase in my app. i want to get all the data under a child from firebase database and compare it with an already existing array to find the missing values and load them in tableview i had added the code i use to perform this and in that the for loop is called every time when new child is found and i want to perform that for loop after getting all the values from the firebase database. is there any way to perform this or is there any way to know whether the firebase had retrieved all the data. Thanks in advance
func fetchUsers()
{
ingredientMasterArr.removeAll()
refhandle1 = ref.child("ingredients").observeEventType(.ChildAdded, withBlock:
{ (snapshot) in
if let dictionary = snapshot.value as? [String : String]
{
let ingredients = IngredientsClass()
ingredients.id = dictionary["id"]
ingredients.ingredient_name = dictionary["ingredient_name"]
// ingredients.category
ingredientMasterArr.append(ingredients)
}
FilteredIngMasterArr.removeAll()
let temp = IngredientsClass()
for MasterID in ingredientMasterArr
{
if (ShopIngKeysArr .contains(MasterID.id!)){
print("if",MasterID.ingredient_name)
}
else
{
print("else",MasterID.ingredient_name)
temp.id = MasterID.id
temp.ingredient_name = MasterID.ingredient_name
FilteredIngMasterArr.append(temp)
}
}
self.tbl_ingMaster.reloadData()
})
}
Using the .Value event type instead of .ChildAdded should give you all the results at once:
refhandle1 = ref.child("ingredients").observeEventType(.Value, ...
Read the firebase documentation on retrieving data for more details.

Resources