How to Check for Value in Firebase That Is Held Under a Autoid Child

Reading Firebase child by auto ID swift

Here's the code to read the Firebase structure proposed in the question

let planitsRef = self.ref.child("planits")
planitsRef.observeSingleEvent(of: .value, with: { snapshot in

for child in snapshot.children {
let planSnap = child as! DataSnapshot
let planDict = planSnap.value as! [String: Any]
let title = planDict["plan_title"] as! String
let senderId = planDict["sender_id"] as! String
print("plan title: \(title) senderId: \(senderId)")
let peopleOnPlanitSnap = planSnap.childSnapshot(forPath: "people_on_planit")

for peopleChild in peopleOnPlanitSnap.children {
let peopleChildSnap = peopleChild as! DataSnapshot
let userSnapDict = peopleChildSnap.value as! [String: Any]
let userId = userSnapDict["user_id"] as! String
print(" userId: \(userId)")
}
}
})

and the output

plan title: Some title  senderId: 39FdLfdIO8832
userId: uid_0
userId: uid_1

-- A couple of notes --

Since the associated users appear to be stored by their user Id and that's the only data stored within that node, you may want to change this node

people_on_planit
-LEmh6IxqguVBJEwghZv (auto ID)
userID: "kkdiEW0D9"

to look like this

people_on_planit
uid_x: true //uid_x would be kkdiEW0D9 etc
uid_y: true

it's a bit shallower and cleaner and requires less code to read it. Also, you can query it more easily if that ever comes up.

also note that I changed the naming convention slightly; you are welcome to format keys however you want but I went with keys like plan_title instead of PlanIt Title and sender_id and user_id instead of senderId and userId. My practice is for actual firebase keys I use all lowercase, underscore instead of spaces, and in code, I use lower/uppercase with no spaces. So if you copy paste my code, you'll need to change those.

How can I access Firebase data under a childByAutoID?

Here we go. An answer to the question. However, and I mentioned in my comment to the question, the structure could be improved. However, there may be more children under each listing child so this answer handles it.

This just print's each authors name but it shows how to get to it so the answer should be expanded for the other child nodes.

let listingsRef = self.ref.child("listings")
listingsRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let autoIdSnap = child as! DataSnapshot
for autoChild in autoIdSnap.children {
let childSnap = autoChild as! DataSnapshot
let dict = childSnap.value as! [String: Any]
let author = dict["author"] as! String
print(author)
}
}
})

Oh, and a better structure may be

listings
childByAutoId
author: "Some author"
listing: 9780184888
childByAutoId
author: "Another author"
listing: 9799292598

Edit: If there will only ever be one and only one childByAutoId under each listing, you can eliminate the loop in the above and do this

let listingsRef = self.ref.child("listings")
listingsRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let autoIdSnap = child as! DataSnapshot //each listing
let childDict = autoIdSnap.value as! [String: Any] //a dict of items within the listing
let firstKey = childDict.keys.first! //the key to the first item
let valuesDict = childDict[firstKey] as! [String: Any] //the values for that key
let author = valuesDict["author"] as! String //the author value
print(author)
}
})

Reading Data stored via Autoid from Firebase Swift

The way I usually do this is by:

ref.child("Phrases").observeSingleEvent(of: .value, with: { snapshot in

let value = snapshot.value as! [String:Any]
let name = value["phrase"] as? String ?? ""
})

Alternatively you could unwrap it first

ref.child("Phrases").observeSingleEvent(of: .value, with: { snapshot in

if let value = snapshot.value as? [String:Any] {
let name = value["phrase"] as? String ?? ""
}
})

Firebase: Accessing Data Stored via childByAutoID

I have the answer. To access the key of the randomly generated autoId, you have to pass it as a FIRDataSnapShot.

for snap in snapshot.children.allObjects {

let id = snap as! FIRDataSnapshot

print(id.key)

}

This will give you the randomly generated keys.

Accessing Firebase Data inside unique AutoID

The issue you're having is that you're trying to dig deeper but can't as you don't have a hold of that id. You'll want to use the .childAdded in your reference observation when you want to get inside of a list in your JSON tree when you don't have a hold of that id to get inside - this will be called as many times as there are values inside of Category 1 tree:

let reference = Database.database().reference()
reference.child("Category 1").child("optionSelected").observe(.childAdded, with: { (snapshot) in

let uniqueKey = snapshot.key // IF YOU WANT ACCESS TO THAT UNIQUE ID
print(uniqueKey)

guard let dictionary = snapshot.value as? [String: AnyObject] else { return }

let date = dictionary["date"] as? String
let variableOne = dictionary["Variable 1 Float"] as? Float
let variableOne = dictionary["Variable 2 Float"] as? Float

}, withCancel: nil)

You may also want to avoid using spaces in your database keys to avoid any problems in the near future. I'd stick with the common lowercased underscore practice e.g. "category_1" or "variable_2_float"

Retrieve randomly generated child ID from Firebase

tasksRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
for task in snapshot.children {
guard let taskSnapshot = task as? FDataSnapshot else {
continue
}

let id = task.key
// do other things
}
}

iOS: How to get and shuffle autoID data of users stored in childnode of firebase?

There are several questions within the question so let's address one.

How to select a random node from Firebase Realtime Database. Well, you don't do it with the Firebase API as Firebase doesn't offer that functionality. However, you can still do it.

First lets start with a typical users node

users
uid_0
name: "Frank"
uid_1
name: "Leroy"
uid_2
name: "Henry"
uid_3
name: "Fred"

So if that's the users node, you can use it for this solution. However, many users node have a lot of other data stored in them - and to select a random node we don't care about that data. What we do is create another node that contains only the node keys - this will keep is pretty small, even if there are thousands of users

user_keys
uid_0: true
uid_1: true
uid_2: true
uid_3: true

Then, to select a random node, we load in all of the user keys using .value, iterate over them to load the keys into an array, then a Swift 4 random number generator to select some keys which we load into another array.

Then we iterate over that array to grab the actual user nodes from Firebase. We also don't want duplicates so as we select nodes from the array, we remove those nodes so they are not selected again. Here's a function to select 3 random nodes, retrieve the users data and print the users name.

func getThreeRandomNodesAndPrintUserName() {

var myKeyArray = [String]()

let ref = self.ref.child("user_keys")

//retreives all nodes in the user_keys node
ref.observeSingleEvent(of: .value, with: { snapshot in

for child in snapshot.children { //build the array of keys
let snap = child as! DataSnapshot
let key = snap.key
myKeyArray.append(key)
}

var randomKeyArray = [String]()

for _ in 0...2 { //will iterate three times
let count = myKeyArray.count //get the number of elements
let randomInt = Int.random(in: 0..<count) //get a random index for the array
let randomUserKey = myKeyArray[randomInt]
randomKeyArray.append(randomUserKey)
myKeyArray.remove(at: randomInt) //remove that object so it's not selected again
}

let numberOfKeys = randomKeyArray.count

for i in 0..<numberOfKeys {
let thisUserKey = randomKeyArray[i]
let userRef = self.ref.child("users").child(thisUserKey)
userRef.observeSingleEvent(of: .value, with: { snapshot in
let name = snapshot.childSnapshot(forPath: "name").value as! String
print(name)
})
}
})
}

and then just a call to that function will print three random users names

self.getThreeRandomNodesAndPrintUserName()

and the output for first run

Fred
Frank
Henry

and then the second run

Henry
Leroy
Fred

etc

How can I delete a specific child node in Firebase from UITableViewCell using Swift

Following on from what MHDev has already answered:

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {

if let exerciseName = exercises[indexPath.row].exerciseName {

let ref = FIRDatabase.database().reference().child("userExercises")

ref.queryOrdered(byChild: "exerciseName").queryEqual(toValue: exerciseName).observe(.childAdded, with: { (snapshot) in

snapshot.ref.removeValue(completionBlock: { (error, reference) in
if error != nil {
print("There has been an error:\(error)")
}
})

})

}

exercises.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .left)
}
}

How to get the key from the value in firebase

That's because you're using a ValueEventListener. If the query matches multiple children, it returns a list of all those children. Even if there's only a single matches child, it's still a list of one. And since you're calling getKey() on that list, you get the key of the location where you ran the query.

To get the key of the matches children, loop over the children of the snapshot:

mDatabase.child("clubs")
.orderByChild("name")
.equalTo("efg")
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String clubkey = childSnapshot.getKey();

But note that if you assume that the club name is unique, you might as well store the clubs under their name and access the correct one without a query:

mDatabase.child("clubs")
.child("efg")
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String clubkey = dataSnapshot.getKey(); // will be efg


Related Topics



Leave a reply



Submit