I am trying to execute a Firebase query and it doesn't seem to be working properly. I am trying to access the name of a School I have in the Firebase Database. The database looks like this:
Schools {
Random School Name {
schoolLocation: Random Location
uid: random UUID
}
}
If I use the following code to get the info of the "Random School Name", I get a snapshot of null:
databaseReference.child("Schools").queryEqualToValue("Random School Name").observeSingleEventOfType(.Value, withBlock: { (snapshot: FIRDataSnapshot) in
print(snapshot)
}) { (error: NSError) in
self.displayError("Search Failed", message: "We couldn't search for that - \(error.code): \(error.localizedDescription)")
}
If I use this line of code, however, the query gives me the name of the school back, as I would expect. I want to be able to track if there is an error using observeSingleEventOfType:
let query = databaseReference.child("Schools").queryEqualToValue("Florida Institute of Technology")
print(query)
Why isn't this working?
I think you're querying by priority here, which will only work if your schools have a priority (highly unlikely).
If that is indeed the problem, solve it by being explicit about the ordering: queryOrderedByKey(). Then also be sure to loop over the children in the result, since a query will return a list, even if there's only one result:
databaseReference
.child("Schools")
.queryOrderedByKey()
.queryEqualToValue("Random School Name")
.observeSingleEventOfType(.Value, withBlock: { snapshot in
for childSnapshot in snapshot.children {
print(snapshot)
}
})
Hey Dan you should try this query for retrieving specific data
self. databaseReference.queryOrderedByChild("Schools").queryEqualToValue("Random School Name").observeSingleEventOfType(.Value, withBlock: { snapshot in
print(snapshot.value)
})
This query returns the random school name for the key schools
Related
Im currently learning ropes in Firebase for iOS, so bare with my novice skills.
Below is a screenshot of my database:
gZ7dn2LMkiah is the autoId for a user
LDBTRFVS8dtz and LDBTe4oXs are autoIds for childId for this user
How can I read the two child nodes inside the node gZ7dn2LMkiah? Cause from my code below, it can only be possible if I have only one child underneath this node, not two
ref = Database.database().reference()
let userId: String = (Auth.auth().currentUser?.uid)!
databaseHandle = ref?.child("childId").child(userId).observe(.childAdded, with: { (snapshot) in
I tried adding childByAutoId after child(userId) but it didn't return any results.
Any help would be appreciated. Thanks in advance.
Database.database().reference(withPath:
"childId").child(userId).observe(.childAdded)
{ (snapshot:DataSnapshot) in
// This will print all sub node
print(snapshot)
}
First of all your db seems incorrect. In first node nick and relation are inside the autoGeneratedKey and in second node nick and relation are outside the key as both are visible while the node is collapse. So these values should be inside autoGeneratedKey. Please change your db structure in correct way. See below screenshot:
This will be your childs table containing all childs for all parents and you can query for a particular parent to get his childs. See below code snippet:
ref.child("childs").queryOrdered(byChild: "parentId").queryEqual(toValue: "123").observeSingleEvent(of: DataEventType.value) { (snapshot) in
if snapshot.exists() {
print("exists")
for child in snapshot.children {
let data = child as! DataSnapshot
print(data.key)
print(data.value)
}
}
else {
print("doesn't exist")
}
}
Output:
-LDBus9Xas3oTccwPN4r
Optional({
nick = Dave;
parentId = 123;
relation = Son;
})
-LDBus9_Uz_qe69e9CXK
Optional({
nick = Susan;
parentId = 123;
relation = Daughter;
})
Where parentId is let userId: String = (Auth.auth().currentUser?.uid)!.
Note 1: I tried adding childByAutoId after child(userId) but it didn't return any results.
Yes it will not work because childByAutoId generate a new key which will never match with existing db keys so you will get nothing.
Note 2: When to use .childAdded
.childAdded event is to listen new entry for the node reference not to fetch the data. To fetch the data for once we should use .observeSingleEvent event.
Note 3:Cause from my code below, it can only be possible if I have only one child underneath this node, not two
No its not possible. This is just because of second node's nick and relation are outside of the key.
My data model
{
"channels":{
"channel_key_0":{
"creator":"pqr",
"name":"Channel-1",
"participant":{
"id_1":"Jack",
"id_2":"Harry"
}
},
"channel_key_1":{
"creator":"xyz",
"name":"Channel-2",
"participant":{
"id_3":"Jerry",
"id_2":"Harry"
}
}
}
}
From given above structure I want to fetch channels of only where participant has value "id_1": "Jack".
I am new to Firebase database. Need help to write this query. I tried few things FIRDatabase.database().reference().child("channels").queryOrdered(byChild: "participant").queryEqual(toValue: "Jack", childKey: "id_1"), but giving me null data.
Improvement in structure is also welcome. My idea is to build personal chat by applying this structure.
Try like this way.
let ref = FIRDatabase.database().reference().child("channels")
ref.queryOrdered(byChild: "participant/id_1").queryEqual(toValue: "Jack")
.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot)
})
cards
cars
-- idcars
-- type:
-- age:
-- user: iduser
users
-- iduser
-- username
-- usermail
ads
-- iduser
-- ads1 : idcars
-- ads2 : idcars
With this structure how it's possible to retrieve all ads for a user together with their own data?
Example:
ads1:
type: golf
age:2
I'm completely new with Firebase
This should be what you need to get the authenticated user and then you can use this model to just retrieve the whole ads branch filtering through it to have everyones ads detail (if you want)
let userID = FIRAuth.auth()?.currentUser?.uid
ref.child("ads").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary // This gets the whole ad branch with all the users ad data
let adsValue = value?["ads1"] as? String ?? "" // This is the specific value of 'ads1' node
// ...
}) { (error) in
print(error.localizedDescription)
}
Maybe like this,
get the user id then put it in ref.child(yourString)
ref = FIRDatabase.database().reference()
ref.child("iduser").observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in })
This will require two read operations, one for the user and one for their ads. See the Firebase documentation for reading data and for querying lists.
If you're having trouble making this work, post the minimal code that reproduces the problem.
I'm trying to get the key of a node based on the child. Here's my structure
Code:
RESTAURANTS
KTNfWKLD0isCsrpys
name: “McDonalds”
loc: “LA”
KTNfWILD0iIkLLekc
name: “KFC”
loc: “LV”
Code:
FIRDatabase.database().reference().child("RESTAURANTS").queryOrderedByChild("name").queryEqualToValue("McDonalds").observeEventType(.Value, withBlock: { (snapshot) in
print(snapshot.key)
}, withCancelBlock: nil)
How can I get the key of "McDonalds" in a query?
You have to use allKeys to get keys from snapshots and than loop it to get key one by one. Try this code
FIRDatabase.database().reference().child("RESTAURANTS").queryOrderedByChild("name").queryEqualToValue("McDonalds").observeEventType(.Value, withBlock: { (snapshot) in
if snapshot.exists() {
for key in (snapshot.value?.allKeys)!{
print(key)
}
}
}
As #Frank van Puffelen said, This way of iterating loses the ordering of the child nodes. If you want to get ordered list than use snapshot.children first
Coming from Parse, I have heavily relied on the containedIn query to collect the right data. In Parse, I might have had an array of objectIds and queried for all objects with those ids. I am looking to achieve the same on Firebase.
I understand that it is important to flatten data, but I don't see how this helps with the problem. Let's say I have a chat room with a list of users inside it. I collect that data and now have an array of usernames. I would like to now navigate to the users in the database and retrieve all that match one element inside this username array. How can I accomplish something like this?
For example, a set of users in a official Firebase example:
{
"users": {
"alovelace": { ... },
"ghopper": { ... },
"eclarke": { ... }
}
}
I would like to perform a query to download the following users:
["alovelace", "eclarke"]
While a general answer would be helpful, an answer in Swift would be best. Thank you.
An example is that they are the two members of a chat room. Or that
the current user is following them.
So a theoretical users node
users
alovelace
followed_by
bill: true
frank: true
in_chat_room: room_42
location: France
ghopper
followed_by
jay: true
in_chat_room: room_27
location: USA
eclarke
followed_by
frank: true
in_chat_room: room_42
location: Canada
and some chat rooms
chat_rooms
room_27
ghopper: true
room_42
lovelace: true
eclarke: true
To get the detailed users nodes of users in chat room 42 (lovelace, eclarke)
let usersRef = self.myRootRef.childByAppendingPath("users")
usersRef.queryOrderedByChild("in_chat_room").queryEqualToValue("room_42")
.observeEventType(.Value, withBlock: { snapshot in
for child in snapshot.children {
let location = child.value["location"] as! String
print(location) //prints France and Canada
}
})
To get the users Frank is following (lovelace, eclarke):
let usersRef = self.myRootRef.childByAppendingPath("users")
usersRef.queryOrderedByChild("followed_by/frank").queryEqualToValue(true)
.observeEventType(.Value, withBlock: { snapshot in
for child in snapshot.children {
let userName = child.key as String
print(userName)
}
})
Note that using user names as node key's is generally a bad idea - they should be stored by their uid.
Also note we didn't really do anything with the chat_rooms node but to maintain the relationship, having nodes refer to each other can be useful for observing changes etc.
Edit:
In response to a comment, here's the structure for each user to show who they are following instead of who is following the user
users
alovelace
following_user
bill: true
frank: true
in_chat_room: room_42
location: France
with this structure, alovelace is following bill and frank.
To get all of the users following frank:
let usersRef = self.myRootRef.childByAppendingPath("users")
usersRef.queryOrderedByChild("following_user/frank").queryEqualToValue(true)
.observeEventType(.Value, withBlock: { snapshot in
for child in snapshot.children {
let userName = child.key as String
print(userName)
}
})