在两个字段上同时使用firestore.where()

时间:2019-06-06 16:57:56

标签: javascript node.js firebase google-cloud-firestore

我有以下文件的存储库:

[
  {
    start:       { geohash: 'u3qchtmpuy2d' },
    destination: { geohash: 'u3qcjvxfh9cs' },
    timestamp:   '28 June 2019 at 20:24:00 UTC+2',
    ...
  }
]

我试图这样查询它(它的Firestore Web SDK)

// 5-characters geohash is 4.89km × 4.89km
const start = 'u3qch';
const destination = 'u3qcj';
const timestamps = {
  min: firestore.Timestamp.fromDate(
    moment(someDateTime).subtract(10, 'minutes').toDate()
  ),
  max: firestore.Timestamp.fromDate(
    moment(someDateTime).add(10, 'minutes').toDate(),
  ),
};

firestore
  .collection('deliveries')
  .where('start.geohash', '>=', start)
  .where('start.geohash', '<', geohashEnd(start))
  .where('destination.geohash', '>=', destination)
  .where('destination.geohash', '<', geohashEnd(destination))
  .where('timestamp', '>=', timestamps.min)
  .where('timestamp', '<', timestamps.max)
  .get()

>=<的组合来自Firestore: query documents by startsWith a string,因此具有geoHashEnd()的功能(不在此问题的范围之内)。

它导致了以下错误:

  

FirebaseError:无效的查询。不等式(<,<=,>或> =)的所有过滤器都必须位于同一字段上。但是您在'start.geohash'和'destination.geohash'上有不等式过滤器

我的问题:通过两个geohash字符串和一个附加字段一次查询我的Firestore集合的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

根据有关stable的官方文档:

  

查询限制

     

Cloud Firestore不支持以下类型的查询:

     
      
  • 如上一节所述,在不同字段上具有范围过滤器的查询。
  •   

如您所见,Cloud Firestore只能对单个字段执行范围过滤,而不能对您打算进行的多个字段进行范围过滤。最合理的解释是Firestore在这种情况下不能保证其性能。 Firestore必须能够在单个流中返回查询的所有结果。

要解决此问题,您将不得不两次查询数据库,并在客户端合并这些查询的结果。这不是完美的,因为您需要查询两次,但我认为它可以解决问题。

还请注意,在地理哈希上使用范围过滤器进行查询不会返回非常准确的结果。为此,我建议您观看Frank van Puffelen关于该主题的精彩视频: