Итак, в настоящее время я использую геохэши для выполнения запросов на основе местоположения как таковых (после этого сообщения stackoverflow: from-a-point">Поиск геохэшей определенной длины в радиусе от точки)
public extension CLLocationCoordinate2D {
func boundingBox(radius: CLLocationDistance) -> (max: CLLocationCoordinate2D, min: CLLocationCoordinate2D) {
// 0.0000089982311916 ~= 1m
let offset = 0.0000089982311916 * radius
let latMax = self.latitude + offset
let latMin = self.latitude - offset
// 1 degree of longitude = 111km only at equator
// (gradually shrinks to zero at the poles)
// So need to take into account latitude too
let lngOffset = offset * cos(self.latitude * .pi / 180.0)
let lngMax = self.longitude + lngOffset
let lngMin = self.longitude - lngOffset
let max = CLLocationCoordinate2D(latitude: latMax, longitude: lngMax)
let min = CLLocationCoordinate2D(latitude: latMin, longitude: lngMin)
return (max, min)
}
func isWithin(min: CLLocationCoordinate2D, max: CLLocationCoordinate2D) -> Bool {
return
self.latitude > min.latitude &&
self.latitude < max.latitude &&
self.longitude > min.longitude &&
self.longitude < max.longitude
}
}
func getGeohashPrefix(){
let loc = CLLocationCoordinate2D(latitude: lat!, longitude: long!)
MBR = loc.boundingBox(radius: 16093.4) //16093.4 meters = 10 miles
//corners = [NorthWest, SouthWest, SouthEast, NorthEast] in lat n long
let corners = [CLLocationCoordinate2D(latitude: MBR.0.latitude,longitude: MBR.1.longitude),
MBR.1, CLLocationCoordinate2D(latitude: MBR.1.latitude, longitude: MBR.0.longitude),
MBR.0]
var geohashes_of_corners: [String] = []
for corner in corners {
geohashes_of_corners.append(corner.geohash(length: 12))
}
geohashes_prefix = geohashes_of_corners.longestCommonPrefix()
}
var query: Query = db.collection("Users").whereField("geohash",isGreaterThanOrEqualTo: geohashes_prefix).whereField("geohash",isLessThanOrEqualTo: geohashes_prefix + "~").order(by: "geohash", descending: false)
query.getDocuments { (querySnapshot, err) in
if err != nil{
print("error getting da documents")
}else{
if querySnapshot!.isEmpty{
return completion(arr_of_people)
}
for document in querySnapshot!.documents {
let d = document.data()
let isPersonWithin = CLLocationCoordinate2D(latitude: (d["loc"] as! GeoPoint).latitude, longitude: (d["loc"] as! GeoPoint).longitude).isWithin(min: self.MBR.1, max: self.MBR.0)
if !isPersonWithin{
continue
}
arr_of_people.append([d["firstName"] as! String, d["lastName"] as! String])
}
return completion(arr_of_people)
}
}
Как видите, я запрашиваю документы с определенным префиксом, а затем СНОВА фильтрую эти документы на клиенте. Это безопасно? Если нет, то каков обходной путь? Использовать облачные функции, другой алгоритм (предложите, если он у вас есть) или что-то еще?