Amazon web services 按距离排序查询需要读取整个数据集吗?

Amazon web services 按距离排序查询需要读取整个数据集吗?,amazon-web-services,amazon-dynamodb,Amazon Web Services,Amazon Dynamodb,要在DynamoDB中执行地理查询,AWS()中有一些库。但要按距离对地理查询结果进行排序,必须读取整个数据集,对吗?如果geoquery生成大量结果,如果按距离排序,则无法分页(在后端,而不是对用户),是吗?您是正确的。要按照距离任意位置的距离对所有数据点进行排序,必须从DynamoDB表中读取所有数据 在DynamoDB中,只能使用存储在DynamoDB表中并用作表或其索引之一的排序键的预计算值对结果进行排序。如果您需要按照距离固定位置的距离进行排序,那么可以使用DynamoDB进行排序

要在DynamoDB中执行地理查询,AWS()中有一些库。但要按距离对地理查询结果进行排序,必须读取整个数据集,对吗?如果geoquery生成大量结果,如果按距离排序,则无法分页(在后端,而不是对用户),是吗?

您是正确的。要按照距离任意位置的距离对所有数据点进行排序,必须从DynamoDB表中读取所有数据

在DynamoDB中,只能使用存储在DynamoDB表中并用作表或其索引之一的排序键的预计算值对结果进行排序。如果您需要按照距离固定位置的距离进行排序,那么可以使用DynamoDB进行排序


可能的解决方法(有限制)

  • TLDR如果您只需要从任意点对X kms范围内的项目进行排序就可以了,这并不是一个很坏的问题
这仍然需要对内存中的数据点进行排序,但由于生成了不完整的结果(通过限制结果的最大范围),问题变得更容易

为此,需要点p的Geohash(从该点测量所有其他点的距离)。假设它是A234311。然后,您需要选择合适的结果范围。让我们在这上面加上一些数字,使之具体化。(我完全是在编造这些数字,因为实际数字与理解概念无关。)

从图形上看,它可能如下所示:

View of A                           View of A23
|----------|-----------|            |----------|-----------|
|          | A21 | A22 |            |          |           |
|    A1    |-----|-----|            |   A231   |    A232   |
|          | A23 | A24 |            |          |           |
|----------|-----------|            |----------|-----------|
|          |           |            |          |A2341|A2342|
|    A3    |     A4    |            |   A233   |-----|-----|
|          |           |            |          |A2343|A2344|
|----------|-----------|            |----------|-----------|  ... and so on.
在本例中,我们的点p位于A224132中。另外,假设我们想要得到400公里内的排序点。A2343是400公里乘400公里,因此我们需要加载A2343及其所有邻居(A2341、A2342、A2344、A2334、A2332、A4112、A4121、A4122)的结果。然后,一旦我们只在内存中加载了这些,那么您就可以计算距离,对它们进行排序,并丢弃任何超过400公里的结果

(只要用户/客户知道400公里以外的数据可能不完整,您就可以保留400公里以外的结果。)


DynamoDB Geo library使用的散列方法与a非常相似-您可能会发现熟悉该方法以及AWS数据库博客中的Z顺序索引对DynamoDB中的多方面查询很有帮助。

不完全如此。查询位置时,您可以按固定的查询值(分区键值)和排序键进行查询,这样您就可以限制查询数据结果,并应用一些过滤

我一直在绞尽脑汁设计DynamoDB地理哈希邻近定位服务。在本例中,客户希望找到其所在区域的所有服务提供商。所有客户和提供商都有一个“g8”密钥,用于存储其精确的geoHash位置(8级)

完成此搜索的公认方法是从主表生成一个二级索引,该索引使用不太准确的geoHash“g4”,这为主查询键提供了更大的区域。我正在为单表设计应用键重载和复合键结构。此设计的目标是返回单个查询中所需的所有数据,二级索引可以按设计复制数据(存储便宜,但cpu和带宽不便宜)

场景1:customer_A.g8_9q5cfmtk所以您发出一个查询,其中GSI1PK=g4_9q5c并返回两个提供者的列表,而不是我想要的三个

但是使用geoHash.neighbor()将返回八个周围邻居,如9q5h(参见下面的参考资料)。这很好,因为9q5h中有一个提供者,但这意味着我必须运行九个查询,一个在中心,八个在邻居,或者运行1-N,直到得到所需的最小结果

但是查询第二个方向,西北,西南,东??这将需要另一个级别的提示,即哪个邻居有更多的结果,而不需要事先知道,除非您对加权结果运行预查询。但这样一来,你就有可能只返回有利的邻居,因为在以前不利的邻居中可能会有新的提供者。您可以对邻居应用一些ML和随机查询来检查当前计数


在采用上述方法之前,我尝试过这种设计

GSI1PK  GSI1SK       providerId    Projected keys and attributes
--------------------------------------------- 
loc     g8_9q5cfmtk  pr_provider1
loc     g8_9q5cfjgq  pr_provider2
loc     g8_9q5fe954  pr_provider3
场景2:customer_A.g8_9q5cfmtk,因此您发出一个查询,其中g8_9q5ca和g8_9q5fz之间的GSI1PK=loc和GSI1SK返回一个包含三个提供者的列表,但大量数据被提取并丢弃

为实现上述查询,X和Y之间的排序条件由以下部分组成。9q5c.Neights().sorted()=9q59、9q5c、9q5d、9q5e、9q5f、9q5g、9qh1、9qh4、9qh5。所以我们可以只使用X=9q59和Y=9qh5,但是在这样一个UTF函数中有超过50个匹配象限(我真的没有在50之后计算)。 关于上面的哈希/大小表,我建议使用 Geohash长度单元格宽度单元格高度 1.≤ 5000km×5000km 2.≤ 1250km×625km 3.≤ 156km×156km 4.≤ 39.1km×19.5km 5.≤ 4.89km×4.89km

能否给出一个具体的示例,说明如何设置表架构以及查询的外观?(不是代码,而是实际数据样本)
GSI1PK  GSI1SK     providerId    Projected keys and attributes
--------------------------------------------- 
g4_9q5c provider   pr_providerId1   name   rating
g4_9q5c provider   pr_providerId2   name   rating
g4_9q5h provider   pr_providerId3   name   rating
GSI1PK  GSI1SK       providerId    Projected keys and attributes
--------------------------------------------- 
loc     g8_9q5cfmtk  pr_provider1
loc     g8_9q5cfjgq  pr_provider2
loc     g8_9q5fe954  pr_provider3