How's it going?
I have the following data structure in Firebase:
reports
.XbCacF7tHosOZxxO(child generated by auto-id)
..userId: "XvSjDkLsaA8Se"
..message: "Text goes here"
..latitude: "30.123131"
..longitude: "50.3313131"
.Yoa7HsgTuWm97oP(child generated by auto-id)
..userId: "XvSjDkLsaA8Se"
..message: "Text goes here 2"
..latitude: "30.99999"
..longitude: "50.99999"
users
.XvSjDkLsaA8Se
..name: "John"
..email: "john#email.com"
The idea of the app is that users can make multiple "reports".
In future if I have hundreds of "reports" I don't want it to overload my query. So I'm trying to find a way using Geofire query.
My question is: Is there any way of getting only the "reports" near me using the radius feature from Geofire and the latitude and longitude from "reports"?
Thanks!
I've just found a way of doing that.
I had to save my Geofire node "reports_locations" with the same id generated by Auto Id at the moment of the creation of the report.
The func that my app saves the data on Firebase:
//Save data to Firebase Database
let key = report.childByAutoId().key
report.child(key).setValue(dataToSaveInFirebase)
//Save data to Geofire node
let userLocal = database.child("reports_locations")
let geoRef = GeoFire(firebaseRef: userLocal)
let location = CLLocation(latitude: self.localUser.latitude, longitude: self.localUser.longitude)
geoRef?.setLocation(location, forKey: key)
I hope it can help other people.
Related
I am currently trying to structure and organize my Firestore Database in my app. Essentially, the first collection of my app will contain my "users" with documents labeled with the email of every user who signs up. I was successfully able to label each document in my "users" database by referencing the Authentication module of Firebase but cannot seem to append data under the individual document paths. I don't know if this is bad practice or not, but this application is for demonstration purposes.
This works successfully in creating an email references in the docs
let db = Firestore.firestore()
db.collection("users").document("\(userEmail)").setData(["firstname":firstname, "lastname":lastname, "uid": result!.user.uid,"email address": email ]) { (error) in
if error != nil {
self.showError("Email has already been used")
This is where I have a problem and the all of the new information is being stored under the a FIRDocumentReference
let iceName1 = iceName1TextField.text!
let iceNumber1 = iceNumber1TextField.text!
let iceName2 = iceName2TextField.text!
let iceNumber2 = iceNumber2TextField.text!
let currentUserEmail = Auth.auth().currentUser!.email
//using this, we can recieve the users email. I don't really know how else to recieve user email so we will need to have someone do that.
let docData: [String : Any] = ["ICE-Name-1" : iceName1 , "ICE-Number-1" : iceNumber1 , "ICE-Name-2" : iceName2, "ICE-Number-2" : iceNumber2]
let userEmail = db.collection("users").document("\(String(describing: currentUserEmail))")
// apparently the document that I am describing above may not exist, therefore, swift is creating document references that are no existent. We need to fix this.
//store data into firebase
let db = Firestore.firestore()
db.collection("users").document("\(userEmail)").setData(docData)
//this appends following information to firebase database
saveLabel.alpha = 1
In the provided code, you are passing a FIRDocumentReference instance as a string to collection.document(). When you stringify an object instance without a description string, it becomes something like <ClassName 0xHexBasedMemoryAddress>.
Try something like this instead:
let userEmailDoc = db.collection("users").document("\(String(describing: currentUserEmail))")
userEmailDoc.setData(docData)
I am building an app where users can upload a location to a Firebase realtime database using GeoFire. The locations need to be associated with the specific user who uploaded them, and accompany other information input by the user. Right now, the code looks like this:
let key = Auth.auth().currentUser!.uid
let subkey = Int.random(in: 1..<100000)
let object: [String: Any] = [
"Type": type.text!,
"Contact": contact.text!,
"Price": price.text!,
"Availability": availability.text!
]
geoFireRef.child("\(key)").child("\(subkey)").setValue(object)
let location = manager.location!
geoFire.setLocation(location, forKey: "\(subkey)")
All of the data gets uploaded, including the location. All of the data entered by the user goes together into a new child of the user ID. However, the location data goes into a separate child outside of the user ID. The name of the new child is the same random number that is used to name the child containing the other data. However, again, the location data is stored outside of the user ID. Is there a method I can use to get the location data into the same child within the user ID? I've tried things like geoFireRef.child("\(key)").child("\(subkey)").setLocation(location) but such a method does not seem to exist. Is there a method I can use?
example of the database
Basically, what I've decided to do is, instead of using the setLocation method, I will just I declared let latitude = location.latitude and let longitude = location.longitude and uploaded those as values for keys called "latitude" and "longitude" to the database with the other dictionary entries. This works for my purposes.
First time asking a question here, so sorry if I do it wrong.
Anyways. I'm using Firebase Database to store "Results" in my Quiz app. When data is store it looks like this
Results
-LjQ34gs7QoL1GMufiMsaddclose
Score: xx
UserName: xx
-LjQ3NeCoDGob8wnhstH
Score: xx
UserName: xx
I would like to access score and username from it and display it in a HighScore tableview. Problem is - I can get the "Results" node, but because of the id of the results (ie LjQ34gs7QoL1GMufiMsaddclose) I don't know how to access the score and username.
I got the data snapshot​, but not sure how to "bypass" the id to get to score and username.
Hope I made it at least a bit clear, what the problem is.
let ref = Database.database().reference().child("Results")
ref.observe(.value) { (DataSnapshot) in
print(DataSnapshot.value as Any)
}
You current code gets you a single snapshot with the results of all users. You'll need to loop over the child snapshots to get the result of each user, and then look up their specific properties with childSnapshot(byName:):
let ref = Database.database().reference().child("Results")
ref.observe(.value) { (snapshot) in
for case let userSnapshot as DataSnapshot in snapshot.children {
print(userSnapshot.childSnapshot(forPath: "Score").value)
}
}
Also see:
How to get all child data from firebase without knowing the path
Iterate through nested snapshot children in Firebase using Swift
How do I loop through and get all the keys of the nested nodes in firebase?
Retrieving Data using Firebase Swift
And probably some more from this list.
If I have some data in the Firebase real-time database like this
root--.
|--stuff--.
|--1
|--2
|--3
|--4
|--5
|--6
|--7
where all those numbers are keys that contain more data, and I want to delete all the keys less than or equal to 4, how do I do that without downloading the entire "stuff" branch?
With swift I think I can query the keys in that range by
let ref = FIRDatabase.database().reference().child("stuff")
let query = ref.queryEnding(atValue: 4)
but I don't know how to retrieve the key names themselves so that I can delete them sort of like this pseudocode
for key in queryResults {
let ref = FIRDatabase.database().reference().child("stuff/\(key)")
ref.setValue(nil)
}
(In reality I'm dealing with timestamp keys and I want to delete data branches that have gotten too old.)
Not sure how to do it in swift, but you can do it with orderByKey.
.database().reference()
.child("stuff")
.orderByKey()
.startAt(STARTING_TIMESTAMP)
.endAt(ENDING_TIMESTAMP)
And then loop over the ids of the corresponding result.
This will download all information for those children though. If you don't want that you'll have to store it somewhere else to easily delete it.
Sample Swift 3 / Firebase 2.x code to get the keys from a snapshot
for child in (snapshot?.children)! {
let snap = child as! FDataSnapshot
print(snap.key)
}
I'm moving my project over to Firebase from Swift. Firebase user's don't have usernames but I'm allowing them to save a display name which works more like a attribute than an actual object. How can I get users to query for other users/"friends" using case in sensitive text?
You can easily accomplish this task. We don't know how your current data is structured but here's an example
users
user_id_0
dsplay_name: "Smokey"
lower_case_name: "smokey"
user_id_1
display_name: "Bandit"
lower_case_name: "bandit"
When you create a user in Firebase, create a node in the /users node with their uid as the node name, and then display_name and lower_case_name as children
When you write your data to the users node, just lower case the display name when you are writing to the lower_case_name child:
let lowerCaseString = displayNameString.lowercaseString
let userRef = the users uid
let userData = ["display_name": "Bandit", "lower_case_name": lowerCaseString]
userRef.setValue(userData)
Then you query on the lower_case_name child using a lower case string.
ref.queryOrderedByChild("lower_case_name").queryEqualToValue("bandit")
.observeEventType(.ChildAdded, withBlock: { snapshot in
}