swift - 使用 GeoHash 时何时使用复合查询?
问题描述
我需要获取与当前用户偏好匹配的 x 半径内的所有用户。
所以我开始从 Firebase 实现 geohash,文档很棒,我的问题可能很傻,但我不知道什么时候使用我所有的复合查询......(whereField)我在“查询中的查询”中指定它们在下面,但我感觉这不是正确的位置。使用 geohash 时如何使用复合查询?
//MARK: - GET MATCHES WITH GEOHASH
func getMatchesNearMe(radius: Double) {
// Find matches within 50km of my location
let user = UserService.shared.user
let center = CLLocationCoordinate2D(latitude: user.latitude ?? 0, longitude: user.longitude ?? 0)
let radiusInKilometers: Double = radius
// Each item in 'bounds' represents a startAt/endAt pair. We have to issue
// a separate query for each pair. There can be up to 9 pairs of bounds
// depending on overlap, but in most cases there are 4.
let queryBounds = GFUtils.queryBounds(forLocation: center,
withRadius: radiusInKilometers)
let queries = queryBounds.compactMap { (any) -> Query? in
guard let bound = any as? GFGeoQueryBounds else { return nil }
return db.collection("users")
.order(by: "geohash")
.start(at: [bound.startValue])
.end(at: [bound.endValue])
}
var matchingDocs = [Matches]()
// Collect all the query results together into a single list
func getDocumentsCompletion(snapshot: QuerySnapshot?, error: Error?) -> () {
guard let documents = snapshot?.documents else {
print("Unable to fetch snapshot data. \(String(describing: error))")
return
}
print("\nDocs: Count \(documents.count)")
for doc in snapshot!.documents {
var m = Matches()
m.latitude = doc.data()["latitude"] as? Double ?? 0
m.longitude = doc.data()["longitude"] as? Double ?? 0
let coordinates = CLLocation(latitude: m.latitude ?? 0, longitude: m.longitude ?? 0)
let centerPoint = CLLocation(latitude: center.latitude, longitude: center.longitude)
m.id = doc.data()["id"] as? String ?? ""
m.name = doc.data()["name"] as? String ?? ""
m.birthdate = doc.data()["birthdate"] as? Date ?? Date()
m.gender = doc.data()["gender"] as? String ?? ""
m.datingPreferences = doc.data()["datingPreferences"] as? String ?? ""
m.height = doc.data()["height"] as? Int ?? 0
m.imageUrl1 = doc.data()["photo1"] as? String ?? ""
m.imageUrl2 = doc.data()["photo2"] as? String ?? ""
m.imageUrl3 = doc.data()["photo3"] as? String ?? ""
m.imageUrl4 = doc.data()["photo4"] as? String ?? ""
m.imageUrl5 = doc.data()["photo5"] as? String ?? ""
m.imageUrl6 = doc.data()["photo6"] as? String ?? ""
m.Q1day2live = doc.data()["Q1day2live"] as? String ?? ""
m.QlotteryWin = doc.data()["QlotteryWin"] as? String ?? ""
m.QmoneynotanIssue = doc.data()["QmoneynotanIssue"] as? String ?? ""
m.bucketList = doc.data()["bucketList"] as? String ?? ""
m.jokes = doc.data()["jokes"] as? String ?? ""
// We have to filter out a few false positives due to GeoHash accuracy, but
// most will match
let distance = GFUtils.distance(from: centerPoint, to: coordinates)
print("MatchName: \(m.name), distance: \(distance) \tlat: \(m.latitude), \(m.longitude)")
if distance <= radiusInKilometers {
matchingDocs.append(m)
}
} //end for loop
self.matches = matchingDocs
self.usersLoaded = true
}
// After all callbacks have executed, matchingDocs contains the result. Note that this
// sample does not demonstrate how to wait on all callbacks to complete.
for query in queries {
query
.whereField("gender", in: ["Women", "men"])
.whereField("conversations", notIn: [user.name])
//.getDocuments(completion: getDocumentsCompletion)
.addSnapshotListener(getDocumentsCompletion)
}
print("Docs: \(matchingDocs.count)")
}
解决方案
如果您想为从 GeoFire 获得的查询添加其他条件,您可以在此处执行此操作:
return db.collection("users")
.order(by: "geohash")
.start(at: [bound.startValue])
.end(at: [bound.endValue])
.whereField("gender", isEqualTo: "female")
您可能需要为此添加索引,因此请务必检查日志输出中是否存在错误消息(以及指向 Firebase 控制台的链接以快速创建索引)。
推荐阅读
- c++ - 如何在模板类函数中分配结构值?
- apache-spark - Spark SQL在拆分后无法识别空值
- java - 使用堆栈在Java中制作文件/目录树
- docker - docker-compose 并使用带有已安装卷的本地映像
- node.js - 如何从mongodb的多个集合中同时获取数据
- python-3.x - 远程调试时按 F5 在 VS Code 中启动 Docker 容器
- java - 推送通知在android studio中不起作用
- angularjs - 如何找出究竟是什么触发了AngularJS中的摘要循环
- mobx - Mobx 状态树入门第 2 部分
- c# - 使用 ImageResizer 调整图像流的大小