select Firebase data with queryOrdered(byChild: "name") queryEqual - ios

i want to select a specific name from my firebase-table (look at the picture). The result to print is always empty. The selected name should be "manni". What is wrong in my code? Thx a lot.
#IBAction func BTSelect(_ sender: Any) {
DBref = Database.database().reference()
let query = DBref?.queryOrdered(byChild: "name").queryEqual(toValue: "manni")
query?.observe(.value, with: { (snapshot) in
for childSnapshot in snapshot.children {
print("childSnapshot:-> \(childSnapshot)")
}
})
}
]1

You'd use queryOrdered(byChild: "name") if each child node has a property name. But in your case, you're querying a node named name and you want to filter on the value of the child nodes. To do that, use queryOrderedByValue:
let query = DBref?.child("name").queryOrderedByValue).queryEqual(toValue: "manni")
This first orders the child nodes of name on their value, and then only returns the ones matching manni.

You need to change this:
let query = DBref?.queryOrdered(byChild: "name").queryEqual(toValue: "manni")
to this:
let query = DBref?.queryOrdered(byChild: "-L5o1LyZRP3J_D-OiguB").queryEqual(toValue: "manni")
since the child: name is not equal to manni. A child inside name is equal to manni.
P.S.: i might have copied this wrong -L5o1LyZRP3J_D-OiguB
The child name is a parent node(not equal to anything), and all those nodes with randomids are the children of the child name.
If you want more than one value to be retrieved, it needs to have the same key (key:value), you can then do the below:
You can change your database like this:
myapp2go-app
randomid
name:manni
randomid
name:manni
randomid
name:ulli
randomid
name:Test
randomid
name:alf
randomid
name:ulf
then in your query, keep it like this:
let query = DBref?.queryOrdered(byChild: "name").queryEqual(toValue: "manni")

Related

Swift Firebase - getting multiple uid's then adding those uid's to a child

I've been thinking about this but I thought I'd post a question to get some more thinking power behind this or to see if this is even possible. I am grabbing multiple uid's and then want to take these uid's and append them to a child in my database and then add further data to them. Since they are uid's I can't access them separately which would be a easy firebase "update values" call, so how could I take this list of uid's and then add them to a child so they are their own separate children and then add values to them? I am just thinking about how I would set this firebase call to say "add each one of these uid's as its own child".
How I am getting the uid's
func getEmployees() {
let employees = Database.database().reference().child("Businesses").child(self.otherUser?["uid"] as! String).child("registered_employees").observe(.childAdded, with: { (snapshot) in
if snapshot.exists() {
let employess = snapshot.childSnapshot(forPath: "uid")
print(employess)
} else {
print("didnt call right values")
}
})
}
sample of data I would add to uid child
let userMessageRef = Database.database().reference().child("user-messages").child(fromID).child(toID)
let messageId = childRef.key
userMessageRef.updateChildValues([messageId!:1])
The code right above ^^^^ I would want the uid's to be in "toID" and then adding the "messageId" to those uid's
I don't know how I could even do each uid separately in the call because of the inability to extract each one and then set the data.
I think I understand so let me try an answer with an example. How we obtain the uid's we want to write is not outlined in the question so let try this:
Suppose we have a users node that stores our users and if they like pizza
users
uid_0 //the Firebase generated uid
name: "Richie"
likes_pizza: true
uid_1
name: "Marion"
likes_pizza: false
uid_2
name: "Fonzi"
likes_pizza: true
uid_3
name: "Howard"
likes_pizza: false
what we want to do it to get the users that like pizza, craft a new node and store each of the uid's as a parent and then a child of their name.
let usersRef = self.ref.child("users")
let pizzaQueryRef = usersRef.queryOrdered(byChild: "likes_pizza").queryEqual(toValue: true)
pizzaQueryRef.observeSingleEvent(of: .value, with: { snapshot in
guard let allUsers = snapshot.children.allObjects as? [DataSnapshot] else {return}
for user in allUsers {
let key = user.key
let name = user.childSnapshot(forPath: "name").value as! String
let pizzaRef = self.ref.child("pizza_lovers")
let aPizzaLoverRefUid = pizzaRef.child(key).child("their_name")
aPizzaLoverRefUid.setValue(name)
}
})
so this code queries for all users that like pizza (which enables us to access their uid's), and then (per the question) append them to a child in the database and then add further data to them
and then want to take these uid's and append them to a child in my
database and then add further data to them
the result is
pizza_lovers
uid_0
their_name: "Richie"
uid_2
their_name: "Fonzi"
Let me know if I misunderstood the question and I will update.

Firebase Database Read childByAutoId

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.

Firebase Access a children if I don't know two childs who have unknown ids

How can I access the data of the children memberId or name and photoURL of the child "members"?
You can see the structure of my database in images.
I tried to use queryOrdered and queryEqual but I just can use it one time
I tried like that because I know the room.key who is the "key" on the database.
let refParticipants = refDatabase.child("markers").queryOrdered(byChild: "key").queryEqual(toValue: room.key)
refParticipants.observe(.childAdded, with: { snapshot in
...
}
I use Swift 3.1
I update my answer with that screenshot:
I think you are asking how to access the child nodes of
/markers/oHQ.../members/9oBKY...
Let's simply the structure for this answer
markers
marker_0
members
member_0
name: "J"
member)1
name: "K"
and then the code that will access each member within the members node and print their name
let markersRef = self.ref.child("markers")
let marker0Ref = markersRef.child("marker_0")
let membersRef = marker0Ref.child("members")
membersRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let name = dict["name"] as! String
print(name)
}
})
and the output will be
J
K
Since you know the parent node (oHQa...), which contains the child node 'members', it doesn't really matter as to what each members key is since you are iterating over them.
However, if you are wanting to query for certain members or other member data, you may want to consider flattening the database a bit like this
markers
oHQa...
//marker data
marker_members
member_0
name: "J"
member_of: "oHQa..."
member_1
name: "K"
member_of: "oHQa..."
With this structure you can query for all the members of any marker or query for all members whose name is "J" etc.
As a side note, in the structure in the question you have the member_id as both the key as well as a child which is unnecessary. If it's the key then you can always directly access that node without a query.

How to display data from nested firebase node in swift?

The following is my database design in firebase
- Sports
- MainCategory (hypothetical category name)
- SubCategory1
- K_tgbBt6Vx0-kkg7e63
- name:football
- K_tgbBt6Vx0-kkg7a99
- name:golf
- Subcategory2
- K_tgbBt6Vx0-kkgad21
- name:Snooker
- K_tgbBt6Vx0-kkg7e00
- name:Table Tennis
- MainCategory2
- SomeOtherSubCategory1
-K_tgbBt6Vx0-kkg7e00
My Aim: To get all the sports under the sports node and display them category wise(i.e MainCategory and Sub category) in a uicollectionview and allow the user to select sports of his choice.
Eg. display
Main Category1
SubCategory1
Football, Golf
SubCategory2
Table Tennis, Snooker
Main Category2
SomeOtherSubCategory1
Hockey,Tennis
The following approaches only take me one level deeper in the node
rootref.child("sports").observe(.value, with: { (snapshot) in
let mainCategory = snapshot.key
for child in snapshot.children{
print(child)
}})
rootref.child("sports").observe(.childAdded, with: { (snapshot) in
let mainCategory = snapshot.key
let mySnapshot = snapshot.value! as! NSDictionary
}) { (error) in
print(error.localizedDescription)
}
Also if there is any other way i could structure my database, kindly let me know
`rootref.child("sports").observe(.value, with: { (snapshot) in
//This gets your mainCategory names
let mainCategory = snapshot.key
for child in snapshot.children{
print(child)
}})
rootref.child("sports").observe(.childAdded, with: { (snapshot) in
let mainCategory = snapshot.key
let mySnapshot = snapshot.value! as! NSDictionary
}) { (error) in
print(error.localizedDescription)
}
//Now what you need to do is another snapshot to get the sub categories. It would be something like this:
rootref.child("sports").child("Sub-Category").observe(.value, with: { (snaps) in
//Same steps as you did above
})
`
It's cool to know that a man like you with 2.5k reps is asking such a question. I assume you know MVC, of course in the future, you'd want a reusable Service Class to handle Firebase requests and Model Class to handle the data.
Next, you should know the different ways of observing data on Firebase. There is a Single Event and Event of Type. Read the doc: https://firebase.google.com/docs/database/ios/read-and-write
In structuring your database, Firebase has a doc for that too: https://firebase.google.com/docs/database/web/structure-data
Anyway, I made a sample for you, take a look:
http://www.jsoneditoronline.org/?id=5d9e7067883a538746ace7cdd9e81ebb
I made a new structure, which I believe a better structure, of your databse using jsoneditoronline website. Avoid so much nested nodes as much as possible. See my sample, I made necessary new nodes for faster and easier fetching of data. For example, if you're going to view the link above and download the database and upload it to your Firebase Database, you'll see the structure like so:
As you can see, I have here a parent node called subcategories-sportId, which has child nodes of different subcategories and each of that subcategories, we have the ids of the sports.
Another example, if we would like to get all the sports under subcategory2, we won't be using the data inside our sport node. (see below pic) But instead, we will check the data inside the subcategories-sportid node. Get a reference to that node plus add a child node of the specific subcategory string, then fetch all the sportsIds. Enumerate the sportsIDs and lastly fetch the main data of each sports.
But if we would like to get all the subcategories and main categories of the specific sports, we can use the data inside our sport node (see the above pic)
let cat3 = db.child("API Questions").child("Category3").child("Name")
cat3.observe(FIRDataEventType.value, with:
{ (snapshot) in
let eventDataloc = snapshot.value as? [String: AnyObject] ?? [:]
// self.Cat3Qarray.removeAllObjects()
for (_, value) in eventDataloc
{
let studsmodel = FirebaseStructureCustVM.updateQuestionData(Questiondata: value as![String:Any])
self.Cat3Qarray.add(studsmodel)
//print(studsmodel)
}
self.tableview1.reloadData()
//print snapshot here
})
In the below, the "API Questions" is the "root" and the "Category1" is the "child" of that root if we want to get the "Category1" data such as MaxMarks:"20",Q:"General information",Qid:"Question 1" so you can print the snapshot like this === print("the snap of the cat1 = (snapshot)") === you will get all the data which is inside of the Category1
let cat2 = db.child("API Questions").child("Category1")
cat2.observe(FIRDataEventType.value, with:
{ (snapshot) in
let eventDataloc = snapshot.value as? [String: AnyObject] ?? [:]
for (_, value) in eventDataloc
{
let studsmodel = FirebaseStructureCustVM.updateQuestionData(Questiondata: value as![String:Any])
}
print((snapshot))
})

firebase queryendingatValue("") always returns first child in database

I am trying to do a keyword search using firebase queries but they do not seem to ever retrieve the correct value. Its always the first child of the database. the database is organized using child by autoid. my data looks like this
posts :
-KJj6DMQVcaOIBZ76X03
category:
"cleaner"
dishname:
"Lysol"
likes
8QCQPfShSTdYe1VbCxHK4dkJPFj1:
true
likesCount:
1
picURL:
"https://firebasestorage.googleapis.com/v0/b/dis..."
poster:
"8QCQPfShSTdYe1VbCxHK4dkJPFj1"
price:
"$5"
restaurant:
"house"
-KJj6PaHt9EfXQ5-EU-m
-KJnTUcb3BvZDMI0Pxgo
-KJnTl4giuy5QMvdeEo5
the function that is doing the search looks like this
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
filteredPosts.removeAll()
let postref = firebase.child("posts")
let search = searchController.searchBar.text!
print(search)
let postQ = (postref.queryOrderedByKey().queryEndingAtValue(search))
// postQ.keepSynced(true)
postQ.observeSingleEventOfType(.ChildAdded, withBlock: { (snapshot) in
self.filteredPosts.append(snapshot)
print(snapshot)
self.shouldShowSearchResults = 2
self.tableView.reloadData()
})
searchController.searchBar.resignFirstResponder()
}
It is super frustrating. please help
You are ordering by key, postref.queryOrderedByKey(), and then querying by that key's value queryEndingAtValue(search).
So unless your search variables is one of the childByAutoId values (-KJnTUcb3BvZDMI0Pxgo), I don't think you'll get back what you want.
Instead order by the child property you are searching against. Let's say you want to search by a post's category.
var search = "cleaner"
let categoryQuery = postref
.queryOrderedByChild("category")
.queryEndingAtValue(search)
This would pull back the record of -KJj6DMQVcaOIBZ76X03.

Resources