Reputation: 3046
I have the following Firebase Database structure,
"-KSupX7CppMD1zbqIy0y" : {
"addedByUser" : "zQpb7o18VzYsSoTQtT9DNhOqTUn2",
"content" : "Post 1",
"cost" : "20",
"duration" : "Weekly",
"latitude" : "40.7594479995956",
"longitude" : "-73.9838934062393",
"timestamp" : "Fri 30 Sep"
},
"-KSuphuqO6a0lnrJYUkt" : {
"addedByUser" : "zQpb7o18VzYsSoTQtT9DNhOqTUn2",
"content" : "Post 2",
"cost" : "10",
"duration" : "Daily",
"latitude" : "40.7594329996462",
"longitude" : "-73.9846261181847",
"timestamp" : "Fri 30 Sep"
}
I need to filter the posts within certain distance parameters (less than 50m, 100m, 150m & 200m) I can get the coordinate from the "longitude" & "latitude" but I'm struggling to filter the posts. Any help would be greatly appreciated.
Many thanks in advance. Newbie to Firebase & Swift.
Upvotes: 6
Views: 2873
Reputation: 1805
Use GeoHash
Here is full documentation for it you can use single https://firebase.google.com/docs/firestore/solutions/geoqueries
Add this to your Podfile pod 'GeoFire/Utils'
Insert GeoHash
let latitude = 51.5074
let longitude = 0.12780
let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let hash = GFUtils.geoHash(forLocation: location)
// Add the hash and the lat/lng to the document. We will use the hash
// for queries and the lat/lng for distance comparisons.
let documentData: [String: Any] = [
"geohash": hash,
"lat": latitude,
"lng": longitude
]
let londonRef = db.collection("cities").document("LON")
londonRef.updateData(documentData) { error in
// ...
}
Get filter data
let queries = queryBounds.map { bound -> Query in
return db.collection("cities")
.order(by: "geohash")
.start(at: [bound.startValue])
.end(at: [bound.endValue])
}
Upvotes: 0
Reputation: 9945
For JSON like this:-
UsersLocation :{
autoID1 : {....},
autoID2 : {.....}
}
Try this:-
FIRDatabase.database().reference().child("UsersLocation").queryOrdered(byChild: "lat").queryStarting(atValue: 30).queryEnding(atValue: 60).observeSingleEvent(of: .value, with: {(snap) in
print(snap)
if let snapDict = snap.value as? [String:AnyObject]{
for each in snapDict{
print(each)
}
}
})
}
This will give you all the users with a autoID
Key, with their latitude between 30 and 60, The order in which you retrieve data will be random, so to iterate through them in ascending order you can sort your dictionary that you receive .
Upvotes: 2
Reputation: 1620
Below is a solution you could try. This assumes you have all posts downloaded to the app from Firebase and stored in an array. You could also look into using GeoFire which I have not personally used (But would like to). I believe it allows you to query Firebase by location so you do not first have to download all posts to a user's device and filter on the client side.
// assumes you have set up the app to get the user's current location
var currentLocation: CLLocation?
// Your array of posts downloaded from Firebase
var postArray = [post]()
let metersInTwentyFiveMiles = 40233.6
// You could put this in viewDidAppear after you load the post array from Firebase
for post in postArray {
var distanceInMeters: CLLocationDistance = 0
let postLocation = CLLocation(latitude: post.latitude, longitude: post.longitude)
if let currentLocation = self.currentLocation {
// Set distanceInMeters to the distance between the user's current location and the location of the post.
distanceInMeters = currentLocation.distanceFromLocation(postLocation)
// If this distance is not within 25 miles, remove this post from the array
if self.metersInTwentyFiveMiles < distanceInMeters {
self.posts = self.posts.filter{ $0 != post }
}
}
}
Upvotes: 0