问题描述
我正在尝试使用时间戳和 geohash 查询我的 Firestore 数据库,但结果一直作为空数组返回。如果我只使用 geohash 或只使用时间戳,那么我得到了结果,但是当我将它们一起使用时没有结果。运行此查询时,我也没有在控制台中收到任何错误。我不确定为什么这个查询不起作用,任何帮助将不胜感激。另外值得注意的是,我正在使用 Firebase 文档中建议的方法来处理 geohash 查询。这是查询的代码:
const bounds = geofire.geohashQueryBounds(center,radiusInM);
const promises = [];
for (const b of bounds) {
const query = firebase
.firestore()
.collection('scheduledWorkouts')
.where('date','>=',start) // start is a Firebase timestamp variable
.where('date','<=',end) // end is a Firebase timestamp variable
.orderBy('date')
.orderBy('geohash')
.startAt(b[0])
.endAt(b[1]);
promises.push(query.get());
}
Promise.all(promises)
.then((snapshots) => {
const matchingDocs = [];
for (const snap of snapshots) {
for (const doc of snap.docs) {
const lat = doc.get('location.lat');
const lng = doc.get('location.lng');
// filtering out false positives
const distanceInKm = geofire.distanceBetween(
[lat,lng],center
);
const distanceInM = distanceInKm * 1000;
if (distanceInM <= radiusInM) {
matchingDocs.push(doc.data());
}
}
}
return matchingDocs;
})
.then((matchingDocs) => {
console.log(matchingDocs);
})
.catch((error) => {
console.log(error);
});
解决方法
Firestore 对查询有此限制:
在复合查询中,范围 (,>=) 和不等于 (!=,not-in) 的比较都必须在同一字段上进行过滤。
虽然没有明确提及,但 start*
和 end*
过滤器也属于此限制。
通过使用 geohash,您已经通过将纬度和经度组合在一个可以排序和过滤的单个值中来解决这个限制。但是通过在 date
上添加范围过滤器,您再次遇到了相同的限制。
过滤纬度、经度和日期的唯一方法:
- 对日期使用相等过滤器,将它们以允许的格式存储。例如,如果您想允许过滤特定的一周,您可以以
2021-05-26
格式存储这一天,并对 7 个值执行in
查询。 - 找到一种方法将时间戳与您自己的值类型中的纬度和经度结合起来,类似于 geohash 已经为纬度和经度所做的。这意味着您必须能够有效地表达时间与距离的关系,因此通常仅适用于定义明确的领域。