How to query a child from another child. Firebase(SWIFT) - ios

im developing a delivery app. So I have productos and popular products in firebase this way:
Products
PopularProducts(ID of the product as key and true as value)
How I can query only the products who are popular using those childs?

You need to get array of productosPopulares and then get each object.
let referenceToProductosPopulares = FIRDatabase.database().reference(withPath: "productosPopulares")
referenceToProductosPopulares.observeSingleEvent(of: .value, with: { snapshot in
if let value = snapshot.value as? NSDictionary {
let productosPopIds = value.allKeys as! [String]
// get every object
for id in productosPopIds {
let refToProd = FIRDatabase.database().reference(withPath: "productos").child(id)
refToProd.observeSingleEvent(of: .value, with: { snapshot in
// your value
})
}
} else {
print("productosPopulares")
}
})
Not perfect code. Should make more functions. But this is idea.
Hope it helps

You can query ordered by the esPopular child and only return the children with it equal to true.
let ref = Database.database().reference(withPath: "productos")
let query = ref.queryOrdered(byChild: "esPopular").queryEqual(toValue: true)
query.observe(.childAdded, with: { (snapshot) in
print(snapshot)
}) { (error) in
print(error)
}

Related

Print All Children Columns from Firebase - iOS Swift 4

I have 2 records in my users table
This code below
let fcmTokenRef = Database.database().reference().root.child("users").child(id!).child("fcmToken")
fcmTokenRef.observe(DataEventType.value, with: { (snapshot) in
print(">>",snapshot)
})
will print out the token of a child
How do I adjust my code to print all the tokens for all my children?
You can try
let fcmTokenRef = Database.database().reference().root.child("users").observe(DataEventType.value, with: { (snapshot) in
print(">>",snapshot)
let dic = snapshot.value as! [String:[String:Any]]
Array(dic.values).forEach {
let str = $0["fcmToken"] as! String
print(str)
}
})
You’re requesting a onetime read, hence you’re reading the data once. You need to use .childAdded
Try this:
let fcmTokenRef = Database.database().reference().child(“users”)
fcmTokenRef.observe(.childAdded, with: { (snapshot) in
print(">>",snapshot)
guard let data = snapshot as? NSDictionary else {return}
var each_token = data[“fcmToken”] as? String
print(“all tokens: \(each_token!)”)
})
#puf says something very important:
differences between child added and value firebase
The child_added event fires for each matching child under the node that you query. If there are no matching children, it will not fire.

Swift, Firebase retrieving data from unknown child

I would like to retrieve data from Firebase database child. But I don’t know the child node name.
My database looks like this:
Users
UserID
2017 (I don't know this string. It's 2017, 2018... or something else?)
November (I don't know this string. It's November, January... or something else?)
Key: Value (I need this data)
Key: Value (I need this data)
Key: Value (I need this data)
I tried this:
override func viewDidLoad() {
super.viewDidLoad()
let userID = Firebase.Auth.auth().currentUser?.uid
databaseRef = Database.database().reference().child("Users").child(userID!)
databaseRef.observe(.value, with: { (snapshot) in
var newItems = [Post]()
for item in snapshot.children {
let newPost = Post(snapshot: item as! DataSnapshot)
newItems.append(newPost)
}
self.postArray = newItems
self.tableView.reloadData()
print(newItems)
}) { (error) in
print(error.localizedDescription)
}
}
In your current code you loop over the years already. If you also want to loop over the months, you'll need to add an extra for:
databaseRef = Database.database().reference().child("Users").child(userID!)
databaseRef.observe(.value, with: {(snapshot) in
for year in snapshot.children.allObjects as [DataSnapshot] {
for month in year.children.allObjects as [DataSnapshot] {
print(month.key)
}
}
}){
(error) in
print(error.localizedDescription)
}
This will print the months. You can get properties of the specific month with:
print(month.childSnapshot(forPath:"Key").value)

How to extract child of node in data snapshot

My firebase set up is as such:
Parent_node:{
Type:{
1476663471800:{ //This is a timestamp = Int64(date.timeIntervalSince1970 * 1000.0)
uid: USERS_UID;
}
}
}
how would I access the users uid? I have tried the following code, but its not extracting the UID
self.databaseRef.child("Parent_node/\(Type)").queryLimitedToLast(5).observeEventType(.Value, withBlock: { (snapshot) in
print(snapshot)
if let userDict = snapshot.value as? [String:AnyObject]{
for each in userDict{
let uidExtraced = each
print(uidExtraced)
//("1476663471700", [uid: USERS_UID])
First of all use snapshot.value?.allValues to get values and than parse it...
if snapshot.exists() {
for value in (snapshot.value?.allValues)!{
print(value) // you get [uid: USERS_UID] here
// ... parse it to get USERS_UID
print("user_id -- \(value["uid"])")
}
}
With this method, order of child might be different. For ordered nodes, you can use snapshot.child

How to ensure that the data is not retrieved and appended as a whole each time a new entry is added?

func generateDataForRecents() {
if URLArrayStringThisSeason.count == 0 {
self.activityIndicator2.isHidden = false
self.activityIndicator2.startAnimating()
}
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("palettes").queryLimited(toFirst: 100).observe(.value, with: { (snapshot) in
if let snapDict = snapshot.value as? [String:AnyObject]{
for each in snapDict as [String:AnyObject]{
let URL = each.value["URL"] as! String
self.URLArrayStringRecents.append(URL)
//print(self.URLArrayString.count)
//print(snapshot)
//let pictureTitle = each.value["title"] as! String
print(self.URLArrayStringRecents.count)
}
}
self.whatsNewCollectionView?.reloadData() //Reloads data after the number and all the URLs are fetched
self.activityIndicator2.stopAnimating()
self.activityIndicator2.isHidden = true
})
}
The following code does a retrieval of data each time the function is called, or when a new data is added.
This is extremely useful when the app is first started up or closed and then restarted. However, when the app is running, whenever a new entry is added, the code seemed to run again and thus appending twice the amount of new data.
For example, when there are already 15 entries identified and then suddenly a new entry is added, the array of the URL would contain 15+16 thus amounting to a total of 31.
How do I make it such that the new data is added to the array instead of adding the entire snapshot in?
You do that by listening for .childAdded events, instead of listening for .value:
var query = databaseRef.child("palettes").queryLimited(toFirst: 100)
query.observe(.childAdded, with: { (snapshot) in
let URL = snapshot.childSnapshot(forPath/: "URL").value as! String
self.URLArrayStringRecents.append(URL)
}
Since you have a limit-query, adding a 101st item means that one item will be removed from the view. So you'll want to handle .childRemoved too:
query.observe(.childRemoved, with: { (snapshot) in
// TODO: remove the item from snapshot.key from the araay
})
I recommend that you spend some time in the relevant documentation on handling child events before continuing.
Please check below method. I have use this method not getting any duplicate entry.
func getallNotes()
{
let firebaseNotesString: String = Firebase_notes.URL
let firebaseNotes = FIRDatabase.database().referenceFromURL(firebaseNotesString).child(email)
firebaseNotes.observeEventType(.Value, withBlock: { snapshot in
if snapshot.childSnapshotForPath("Category").hasChildren()
{
let child = snapshot.children
self.arrNotes = NSMutableArray()
self.arrDictKeys = NSMutableArray()
for itemsz in child
{
let childz = itemsz as! FIRDataSnapshot
let AcqChildKey : String = childz.key
if AcqChildKey == AcqIdGlobal
{
if (childz.hasChildren() == true)
{
let dictChild = childz.value as! NSMutableDictionary
self.arrDictKeys = NSMutableArray(array: dictChild.allKeys)
for i in 0..<self.arrDictKeys.count
{
let _key = self.arrDictKeys.objectAtIndex(i).description()
print(_key)
let dictData : NSMutableDictionary = NSMutableDictionary(dictionary: (dictChild.valueForKey(_key)?.mutableCopy())! as! [NSObject : AnyObject])
dictData.setObject(_key, forKey: "notesId")
self.arrNotes.addObject(dictData)
}
}
}
}
self.tableviewNote.reloadData()
}
})
}
As for the query for removed child,
query.observe(.childRemoved, with: { (snapshot) in
print(snapshot)
let URL = snapshot.childSnapshot(forPath: "URL").value as! String
self.URLArrayStringThisSeason = self.URLArrayStringThisSeason.filter() {$0 != URL}
self.thisSeasonCollectionView.reloadData()
})
it will obtain the URL of the removed child and then update the array accordingly.

Firebase and Swift 3 code not executing anymore

I tried to convert my code func by func to Swift 3. I have to say that I had fully working project before. Now I have problem where I have no errors and just some warnings but some of the functions are not being executed. What should cause this?
I only assume that those given functions are faulty because these are the parts where I am not getting anything even print.
These are some of my functions that worked before but not with Swift 3:
//With this I get selected brand products values like product name, nicotine, flavor etc..
let ref = FIRDatabase.database().reference().child("Snuses").queryOrdered(byChild: "Brand").queryEqual(toValue: brandName)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists(){
if let products = (snapshot.value as AnyObject).allValues as? [[String:AnyObject]]{
self.productsValue = products
self.productsTable.reloadData()
}
}
})
//With this fucntion I get the products count.
let ref = FIRDatabase.database().reference().child("Snuses").queryOrdered(byChild: "Brand").queryEqual(toValue: filteredBrands[indexPath.row])
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists(){
if let products = (snapshot.value as AnyObject).allValues as? [[String:AnyObject]]{
var count = (snapshot.childrenCount)
snusProductCountLabel.text = "\(count) products"
}
}
})
//Parse snus brands
func parseSnuses(){
let ref = FIRDatabase.database().reference().child("Brands").queryOrderedByKey()
ref.observe(.childAdded, with: { (snapshot) in
self.brands.append(snapshot.key)
print(snapshot.key)
self.snusBrandsTableView.reloadData()
}){ (error) in
}
Anything I can do different please tell me! Those functions are in different ViewControllers.
Edit: this is my JSON tree
{
"Snuses" : {
"Catch Eucalyptus White Large" : {
"Brand" : "Catch",
"Products" : "Catch Eucalyptus White Large",
"PorionWeight" : 21.6,
"flavor" : "Tobacco, Eucalyptus",
"nicotine" : 8.0,
"PortionsCan" : 24,
"shipping weight" : 39
},
And these are security rules:
{
"rules": {
".read": "true",
".write": "true",
"Snuses": {
".indexOn": "Brand"
}
}
}
I believe the
if let products = (snapshot.value as AnyObject)
.allValues as? [[String:AnyObject]]{
is the issue.
Try this as a test to see if it prints the data from the snapshot:
let ref = FIRDatabase.database().reference().child("Snuses")
.queryOrdered(byChild: "Brand").queryEqual(toValue: brandName)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
let dict = snapshot?.value as! [String: [String:String]]
let productsArray = Array(dict)
for row in productsArray {
print(row)
}
}
})
for a non-swifty test, you can also try this inside the closure instead of the above
let d2 = snapshot?.value as! NSDictionary
let a2 = d2.allValues
for r2 in a2 {
print(r2)
}
one more option:
let q = snapshot?.value as! [String: AnyObject]
let a3 = Array(q)
for r3 in a3 {
print(r3)
}
I don't know what your tableView is expecting in the array but one of those should cover it.

Resources