这是我在尝试将地理位置与Firestore混合时遇到的问题。长话短说-我需要用户所在地附近的餐厅。为了完成地理搜索,我使用Algolia。当我向Algolia发出请求时,它返回一个与Firestore文档id相对应的唯一餐厅id数组。这很管用。
使事情变得复杂的是,我还需要两个条件-我需要将查询限制在平均评分>=8的餐厅。我还想限制返回文档的数量(2、5、20等)。
所以在伪代码中应该是这样的:
db.restaurantsCollection
.documentIds([111, 222, 333, 444, 555, 666, 777, 888, 999])
.whereField("averageRating", isGreaterThanOrEqualTo: 8)
.order(by: "averageRating", descending: true)
.limit(to: 2)
.getDocuments()
我知道到目前为止,Firestore不支持使用多个文档id的查询。那么,执行这种查询的最佳方法是什么?
如果我在文档中将
documentId
设置为id
字段,然后遍历Algolia返回的所有id并执行类似的操作(然后我可以使用纯Swift进行排序和限制):for id in ids {
db.restaurantsCollection
.whereField("averageRating", isGreaterThanOrEqualTo: 8)
.whereField("id", isEqualTo: id)
.getDocuments()
}
但这仍然意味着很多要求。还有其他想法吗?
最佳答案
如果这对任何人都有帮助,我张贴的选项,你可能会考虑,如果你是实现地理查询的方式,我实现他们-用Algolia。所以使用Algolia的方法是保持搜索索引的坐标。
例如:
{
"_geoloc": {
"lng": 8.507785799999999,
"lat": 47.17652589999999
},
"objectID": "1234abcd"
}
objectID对应于餐厅的文档ID或您想要地理查询的任何类型的场所。
然后通过Algolia API创建查询。如果你想得到一个CLLocation周围的所有项,你应该设置它-为此使用
query.aroundLatLng
属性。您还可以以米为单位设置distance
属性。结果将是一个JSON,您的id按距离排序,从最近的开始。到目前为止很好-我们解决了最大的问题-按地理位置查询。
如果我想从我从Algolia得到的所有N个ID中获得最高评价呢?可悲的是,到目前为止还没有API可以通过多个id进行查询。所以这意味着如果我想得到所有得分>=8的餐厅,我需要让N个Firestore文档读取,然后获得最高评价。远非理想。
选择1。
用Algolia数据保存餐厅平均值。
我知道这意味着额外的网络,但这是一个好办法。缺点-每次更新Firestore中的餐厅平均值时,还需要更新Algolia中的餐厅平均值。如果你像我一样用云函数计算平均值,你也需要用Algolia来设置它们。是的,这意味着您需要升级到付费的Firebase计划,因为这是一个外部云功能调用。
现在,您的Algolia负载中已经有了平均值,您可以轻松地获取您所在地区的所有餐厅id,然后根据其Algolia评级客户端对数据进行排序。一旦对id进行了排序,就可以从Firestore请求文档。
选择2。
保存城市名称和国家
您可以将城市和国家名称与您的位置数据一起保存在Firestore中。这样您就可以使用它们进行查询。伪Firestore查询代码:
db.restaurants.where("city" == "current_city").where("country" == "current_country").where("averageRating" >= 8).getDocuments()
然而,这种方法并不十分准确,而且主要适用于大城市。它也不会计算接近你的位置。
我希望这能有帮助。