在 Firestore 中查询 Geohashes
Querying Geohashes in Firestore
最近我一直在研究 Geohashes 和 Firestore。
我的待办事项场景是收集文件(餐厅),每个餐厅都会有 Geohashes 列表,这些列表会交付给。
我想避免在文档 restaurant 中添加 geoashes,因为文档可能比应有的大很多倍。
最初的想法是将所有 geohashes 放在餐厅文档的子集合中,但我发现无法在文档的子集合中执行查询。
第二个想法是将 geohashes 提取到交付区域集合中的顶级。
document:{ restaurantName: "aRestaurant",
deliveryArea: Arraylist<String> }
这种情况下的问题是我将取回餐厅名称列表,然后我需要查询餐厅集合以获取它们,据我所知我无法在查询中执行 OR 操作。
这是我第一次使用文档数据库和 Firestore。任何指导将不胜感激。
I want to avoid adding the geoashes in the document restaurant as the document can be many times bigger than it should be.
是的,不要那样做,因为文件有限制。因此,对于可以放入文档的数据量存在一些限制。根据有关 usage and limits 的官方文档:
Maximum size for a document: 1 MiB (1,048,576 bytes)
如您所见,单个文档中的数据总量不得超过 1 MiB。当我们谈论存储文本时,您可以存储很多,但如果您使用的是复杂对象,这不是一个选项。
The initial idea is to have all of the geohashes in a subcollection of the restaurant document but I found out its not possible to perform queries in subcollection of documents.
这是一个很好的解决方案。您的数据库结构应如下所示:
Firestore-root
|
--- restaurants (collection)
|
--- restaurantId (document)
|
--- geohashes (collection)
|
--- geohashId (document)
|
--- //details about the location
因此,可以让您获取特定餐厅的所有 geohash
对象的查询将完美无缺。
The second idea was to extract the geohashes to top level in a collection of delivery areas
不是一个糟糕的解决方案,但您应该创建一个额外的 get()
调用,以获取餐厅详细信息,但即使这样做,也不是一个糟糕的调用,Firestore 中的嵌套查询没有问题。不需要OR
操作。
编辑: 根据您的评论,是的,您是对的,您无法查询数据库以取回餐厅对象,但我们也有解决方法。在这种情况下,您应该考虑通过添加这样的新集合来扩充数据结构以允许反向查找:
Firestore-root
|
--- geohashes (collection)
|
--- geohashId (document)
|
--- geohashRestaurants (collection)
|
--- restaurantId
|
--- //restaurant details
此技术称为 denormalization
,如您所见,它意味着重复数据。但是您需要知道,对于 Firebase,复制数据没有问题。这是一种很常见的做法,为此,我建议您观看此视频 Denormalization is normal with the Firebase Database。适用于 Firebase 实时数据库,但同样的原则也适用于 Cloud Firestore。
复制数据时,需要牢记一件事。以与添加数据相同的方式,您需要维护它。换句话说,如果你想 update/detele 一个项目,你需要在它存在的每个地方都这样做。
firebaser 在这里
我们用于 Firebase 实时数据库的原始 GeoFire 库通过为 geohashes 提供单独的顶级节点精确地解决了这个问题。该节点下的每个键通常对应于另一个顶级节点中实际实体的键。
所以像这样:
locations
key1: { g: "sa7ads", l: [ 14.5232, -156.17843 ] },
key2: { g: "fds347", l: [ -127.172, 167.1324 ] }
restaurants
key1: { name: "This is the first restaurant", ... },
key2: { name: "This is the second restaurant", ... },
使用此结构,您可以对 /locations
执行地理查询,然后读取 /restaurants/$key
范围内每家餐厅的附加信息。缩放得很好。
我推荐使用与 Cloud Firestore 相同的方法。您将有两个顶级集合:一个包含(较小的)位置数据,另一个包含关于每家餐厅的(较大的)附加数据。这会减少您阅读的数据量,尽管您最终会阅读更多文档。您必须平衡这两者(带宽与文档读取)。
几个月前我给了一个 talk about performing geoqueries on Cloud Firestore 可能值得一试。
最近我一直在研究 Geohashes 和 Firestore。 我的待办事项场景是收集文件(餐厅),每个餐厅都会有 Geohashes 列表,这些列表会交付给。
我想避免在文档 restaurant 中添加 geoashes,因为文档可能比应有的大很多倍。
最初的想法是将所有 geohashes 放在餐厅文档的子集合中,但我发现无法在文档的子集合中执行查询。
第二个想法是将 geohashes 提取到交付区域集合中的顶级。
document:{ restaurantName: "aRestaurant",
deliveryArea: Arraylist<String> }
这种情况下的问题是我将取回餐厅名称列表,然后我需要查询餐厅集合以获取它们,据我所知我无法在查询中执行 OR 操作。
这是我第一次使用文档数据库和 Firestore。任何指导将不胜感激。
I want to avoid adding the geoashes in the document restaurant as the document can be many times bigger than it should be.
是的,不要那样做,因为文件有限制。因此,对于可以放入文档的数据量存在一些限制。根据有关 usage and limits 的官方文档:
Maximum size for a document: 1 MiB (1,048,576 bytes)
如您所见,单个文档中的数据总量不得超过 1 MiB。当我们谈论存储文本时,您可以存储很多,但如果您使用的是复杂对象,这不是一个选项。
The initial idea is to have all of the geohashes in a subcollection of the restaurant document but I found out its not possible to perform queries in subcollection of documents.
这是一个很好的解决方案。您的数据库结构应如下所示:
Firestore-root
|
--- restaurants (collection)
|
--- restaurantId (document)
|
--- geohashes (collection)
|
--- geohashId (document)
|
--- //details about the location
因此,可以让您获取特定餐厅的所有 geohash
对象的查询将完美无缺。
The second idea was to extract the geohashes to top level in a collection of delivery areas
不是一个糟糕的解决方案,但您应该创建一个额外的 get()
调用,以获取餐厅详细信息,但即使这样做,也不是一个糟糕的调用,Firestore 中的嵌套查询没有问题。不需要OR
操作。
编辑: 根据您的评论,是的,您是对的,您无法查询数据库以取回餐厅对象,但我们也有解决方法。在这种情况下,您应该考虑通过添加这样的新集合来扩充数据结构以允许反向查找:
Firestore-root
|
--- geohashes (collection)
|
--- geohashId (document)
|
--- geohashRestaurants (collection)
|
--- restaurantId
|
--- //restaurant details
此技术称为 denormalization
,如您所见,它意味着重复数据。但是您需要知道,对于 Firebase,复制数据没有问题。这是一种很常见的做法,为此,我建议您观看此视频 Denormalization is normal with the Firebase Database。适用于 Firebase 实时数据库,但同样的原则也适用于 Cloud Firestore。
复制数据时,需要牢记一件事。以与添加数据相同的方式,您需要维护它。换句话说,如果你想 update/detele 一个项目,你需要在它存在的每个地方都这样做。
firebaser 在这里
我们用于 Firebase 实时数据库的原始 GeoFire 库通过为 geohashes 提供单独的顶级节点精确地解决了这个问题。该节点下的每个键通常对应于另一个顶级节点中实际实体的键。
所以像这样:
locations
key1: { g: "sa7ads", l: [ 14.5232, -156.17843 ] },
key2: { g: "fds347", l: [ -127.172, 167.1324 ] }
restaurants
key1: { name: "This is the first restaurant", ... },
key2: { name: "This is the second restaurant", ... },
使用此结构,您可以对 /locations
执行地理查询,然后读取 /restaurants/$key
范围内每家餐厅的附加信息。缩放得很好。
我推荐使用与 Cloud Firestore 相同的方法。您将有两个顶级集合:一个包含(较小的)位置数据,另一个包含关于每家餐厅的(较大的)附加数据。这会减少您阅读的数据量,尽管您最终会阅读更多文档。您必须平衡这两者(带宽与文档读取)。
几个月前我给了一个 talk about performing geoqueries on Cloud Firestore 可能值得一试。