【发布时间】:2012-08-04 07:38:11
【问题描述】:
我想知道人们建议在 Amazon Web Services SimpleDB 中进行空间查询的有效方法是什么?
空间查询是指在给定的纬度和经度半径内查找对象。
【问题讨论】:
标签: amazon-web-services amazon-simpledb spatial-query
我想知道人们建议在 Amazon Web Services SimpleDB 中进行空间查询的有效方法是什么?
空间查询是指在给定的纬度和经度半径内查找对象。
【问题讨论】:
标签: amazon-web-services amazon-simpledb spatial-query
SimpleDB 目前不提供任何内置的空间搜索操作,但这并不意味着它不能完成。有几种方法可以在非地理空间感知数据库(如 SimpleDB)中实现地理空间搜索,所有这些方法都围绕着使用数据库检索基于地理空间边界框的粗略第一选择,然后使用过滤应用程序中返回的数据的想法更准确的算法,例如Haversine formula。
您可以将纬度和经度存储为(零填充和标准化)数字属性,然后执行双范围查询 (lat >= minLat and lat <= maxLat and lon >= minLat and lon <= maxLat),但由于这些谓词都不是选择性的(每个谓词匹配很多项目)并不理想(见Tuning Queries)。
更好的方法是使用GeoHashes。
Geohashes 提供任意精度、类似前缀等属性 对于附近的位置,以及逐渐移除的可能性 代码末尾的字符以减小其大小(并逐渐 失去精度)。
作为一个实际示例,Geohash 6gkzwgjzn820 解码为 坐标 -25.382708 和 -49.265506,而 Geohash 6gkzwgjz 将 解码为 -25.383 和 -49.266,如果我们在 同一个区域,比如 -25.427 和 -49.315,我们可以看到它是 编码为 6gkzmg1w(注意类似的前缀)。
来自http://geohash.org/site/tips.html
将您的项目位置作为 GeoHashes,您可以使用 like 运算符来搜索边界框 (where GeoHash like '6gkzmg1w%'),但由于 like 运算符很昂贵 (Comparison Operators),因此更好的方法是将通过将每个 GeoHash 前缀级别(多少取决于您所需的搜索精度)存储为单独的属性(GeoHash6 GeoHash8 等),然后使用简单的等式谓词(where Geohash8 = '6gkzmg1w')来获取数据。
现在谈谈 GeoHashes 的缺点。由于您无法假设 GeoHash 在您的搜索框中居中,因此您还必须搜索所有相邻前缀。 geohash-js 很好地描述了这个过程
Geohash 还具有随着位数减少的性质 (从右边开始),准确度下降。这个属性可以用来做 边界框搜索,因为彼此靠近的点将共享 类似的 Geohash 前缀。
但是,因为给定点可能出现在给定点的边缘 Geohash边界框,需要生成一个Geohash列表 值,以便在一个点周围执行真正的邻近搜索。 因为 Geohash 算法使用 base-32 编号系统,所以它是 可以导出围绕任何其他给定的 Geohash 值 Geohash 值使用一个简单的查找表。
因此,例如,华盛顿特区宾夕法尼亚大道 1600 号解析为: 38.897, -77.036
使用geohash算法,将这个经纬度转换 到:dqcjqcp84c6e
围绕这一点的简单边界框可以描述为 将此 geohash 截断为:dqcjqc
但是,'dqcjqcp84c6e' 不在 'dqcjqc' 中居中,并且搜索 在 'dqcjqc' 内可能会错过一些期望的目标。
因此,我们可以使用 Geohash 的数学属性来 快速计算'dqcjqc'的邻居;我们发现它们是: 'dqcjqf','dqcjqb','dqcjr1','dqcjq9','dqcjqd','dqcjr4','dqcjr0','dqcjq8'
这为我们提供了一个围绕“dqcjqcp84c6e”的边界框,大约 2 公里 x 1.5 公里 并允许仅对 9 个键进行数据库搜索:SELECT * FROM table WHERE LEFT(geohash,6) IN ('dqcjqc', 'dqcjqf','dqcjqb','dqcjr1','dqcjq9','dqcjqd','dqcjr4','dqcjr0','dqcjq8');
转换为 where GeoHash6 in('dqcjqc', 'dqcjqf', 'dqcjqb', 'dqcjr1', 'dqcjq9', 'dqcjqd', 'dqcjr4', 'dqcjr0', 'dqcjq8') 的 SimpleDB 查询,然后您将对结果进行 Haversine 过滤,以便仅获取搜索范围内的项目。
【讨论】:
我将把它留在这里,因为它可能对你有帮助!
14 年前,我们尝试对半径范围内的位置进行地理查找表。显然没有地理空间索引或类似的东西。 实际上只有标准的 SQL 和 Oracle ......无论如何,我们最终将所有 lat/lng 从固定平面场转换为公里。这些天地理空间索引基本上是做什么的。
为了解释它究竟做了什么,它把世界变成了一个平面,你甚至可以通过一些 SQL 技巧来选择半径,甚至可以得到你选择的两个点的距离。由于它也是原始的完整整数,因此查询速度非常快。
这是一个简单的 PHP 示例,看起来非常复杂,但一旦你理解它就很容易 SQL 查询:
【讨论】: