Reputation: 165
I'm using Firebase with swift (SwiftUI to be exact) and since my DB contains many records (more than 10k records) I'm trying only pull the relevant data from the DB (Otherwise it will pull ALL the data every time which will be a waste).
I think that I should use .indexOn but I don't really know what to do (I don't have much experience with json).
This is the code in SWIFT that I tried using:
ref.child("Items").observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
// Doing stuff here.
}
})
This is my data structure:
tbl (the actual table):
items:
____:
serial:
date:
more parameters...:
____:
serial:
date:
and so on...
The blank spots (___:) represents names which were auto generated by Firebase (just random numbers from 0 to the amount of records in the table), and I want to pull by a query the specific record that contains a matching serial.
This is how my rules in Firebase DB looks like:
{
"rules": {
".read": true,
".write": false
}
}
How should I use .indexOn on my Firebase rules? Or is there any other alternative to get what I want?
Thanks in advance.
Update:
I'm trying to get a specific record out of the query. Based on the data structure I specified above, what I'm trying to get is the serial and the date of the child that have a serial number matching to a serial number which I'll input to the query.
Suppose I want to use X8M9320C in the query. What I would like to get is the serial (X8M9320C) and the date back from the table.
Also, the naming for the ___: is an auto generated numbers which are automatically initialized when I upload the json file to Firebase.
Update 2:
The image above represents how the db structure looks.
After some debugging, I saw that after running the query, I'm getting 0 values from the row:
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
The full code:
let serial = "XCM8320CMW"
let myDataRef = self.ref.child("tbl")
let itemsRef = myDataRef.child("items")
let query = itemsRef.queryOrdered(byChild: "serial").queryEqual(toValue: serial)
query.observeSingleEvent(of: .value, with: { snapshot in
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
guard let firstChild = childSnaps.first else {return}
let date = firstChild.childSnapshot(forPath: "date").value as? String ?? "No Date"
print(date)
})
Upvotes: 1
Views: 222
Reputation: 35667
TL;DR
There was a coding issue which I addressed below and also the string the OP is searching for is this
X8M9320C
but what's stored in Firebase is this
Noting all of the white space (space bar characters) before and after the stored string. The two are not equal which is why my query below won't work on it.
-- Longer answer:
To clarify, Firebase does not have tables; it has key: value pairs which are also called parent and child nodes where the parent is the key and the child is a value, which can also be a pair of key: values.
This sounds like a basic Firebase query which is covered here in the documentation.
Given a structure like the one in your question:
my_data
items
item_0
serial: "OU812"
date: "20200427"
more parameters...:
item_1
serial: "X8M9320C"
date: "20200513"
more parameters...:
Here's the query which will query for serial of X8M9320C and print the date from that node. Keeping in mind that a query could return multiple results we need to iterate over all the returned nodes.
func queryForItem() {
let serial = "X8M9320C"
let myDataRef = self.ref.child("my_data")
let itemsRef = myDataRef.child("items")
let query = itemsRef.queryOrdered(byChild: "serial").queryEqual(toValue: serial)
query.observeSingleEvent(of: .value, with: { snapshot in
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
for snap in childSnaps {
let date = snap.childSnapshot(forPath: "date").value as? String ?? "No Date"
print("serial: \(serial) has a date of \(date)")
}
})
}
and the output
serial: X8M9320C has a date of 20200513
If you know there will only ever be nothing returned or one returned node (if the serials are guaranteed to be unique for example) you could eliminate the for loop and do this
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
guard let firstChild = childSnaps.first else {return}
let date = firstChild.childSnapshot(forPath: "date").value as? String ?? "No Date"
print(date)
Upvotes: 2