我正在使用 Firebase 8.10.0 和 Vue js 2.6.14
我正在尝试在 Firestore 中查询距离我所在位置不到 3 公里的文档 并发现我无法在 firestore 中执行此查询,坦白说我很失望 然后在 YouTube 上观看 Frank van Puffelen 的视频“查询 Firebase 和 Firestore”1 我知道执行此查询的最佳方法是通过
Geohash
所以现在我使用ngeohash
将lat long转换为geohash代码,然后使用geofirestore
进行查询(我没有使用geofirestore将数据添加到firestore,因为我找不到添加具有特定id或更新的文档的方法带有 geofirestore 的现有文档)
将 lat long 转换为 geohash 代码
import geohash from "ngeohash";
const ask = async () => {
try {
const loc = await new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, {
enableHighAccuracy: true,
});
});
const { latitude, longitude, accuracy } = loc.coords;
return {
lat: latitude,
lng: longitude,
accuracy: accuracy,
geohash: geohash.encode(latitude, longitude)
};
} catch (err) {
console.log(err);
}
};
将数据添加到firestore
ref.set({
g: {
geopoint: new db.GeoPoint(lat, lng),
geohash: geohash
},
...data
}, { merge: true }).then(() => {
console.log("Done");
});
从 firestore 查询
let query = geocollection.near({ center: new db.GeoPoint(lat, lng), radius: 3 });
query.get().then((data) => {
console.log(data.size);
});
我正在做的事情是正确的吗?这是在 firestore 中按位置查询的最佳方式吗?并且geofirestore是否增加了读数的数量,因为我前段时间做了一个查询,结果只有1000个文档中的5个,但是我发现Firebase控制台中记录了60多个读数。这是正常现象还是应该只有 5 个读数?
Geohashes 允许您查询特定地理区域内的文档。这些区域可能与您指定的特定点的距离重叠,但您通常需要查询多个范围的 geohashes 以获取某个点周围的所有文档。
根据我在您链接的视频中展示的内容对此进行简单的可视化:
所以这里的查询是返回灰色圆圈内的所有文档。但为了获取这些文档,我们需要查询所有四个颜色范围的 geohashes。
如果你的文档分布相对均匀,你可能会得到这样的结果:
此图中的每个图钉都是 Firestore 读取的文档,但只有绿色图钉是属于您实际想要的范围内的文档。
在我的实验中,为了实现文档的均匀分布,您最终会阅读比使用此方法所需的多 2 倍到 10 倍的文档。如果您担心这种过度读取的成本,请考虑使用实时数据库及其 geofire 库进行地理查询。虽然重读是相同的,但计费结构基于带宽,并且地理索引消耗的带宽量非常小。
更新(2024 年 5 月):Firestore 最近添加了在单个查询中的多个字段上具有不等式和范围条件的功能。有关完整详细信息,请参阅在多个字段上使用范围和不等式过滤器进行查询和在多个字段上使用范围和不等式过滤器优化查询的文档。
我还在 Medium 上写了一篇关于此的文章,比较了基于 geohash 的查询与在多个字段上使用范围条件的新方法的成本:如何在 Firestore 上(某种程度上)高效地执行地理查询