首先,我想说我对使用Redis或任何其他空间数据库不感兴趣。我正在尝试在内存geohash范围查询中做一个非常简单的事情,并且正在使用以下软件来计算geohash- geohash-int C package,并且我有一个Cython包装器来在Python 3.6中调用这些API。我正在使用SortedList来存储geohash,我的目标是在内存中进行一个简单的geohash范围查询。
#GeoHash is a Cython wrapper of external C geohash library (link provided)
from geo import GeoHash
from sortedcontainers import SortedList
import numpy as np
import time
minLat = 27.401436
maxLat = 62.54858
minLo = -180.0
maxLo = 179.95000000000002
latGrid = np.arange(minLat,maxLat,0.05)
lonGrid = np.arange(minLo,maxLo,0.05)
geoHash = GeoHash()
print(latGrid.shape,lonGrid.shape)
gridLon,gridLat = np.meshgrid(lonGrid,latGrid)
grid_points = np.c_[gridLon.ravel(),gridLat.ravel()]
sl = SortedList()
geohash1 = {}
t0 = time.time()
for grid_point in grid_points:
lon = grid_point[0]
lat = grid_point[1]
geohash = geoHash.encode(lon,lat,26)
bitsOriginal = geohash["bits"]
sl.add(bitsOriginal)
neighbors = geoHash.get_neighbors(geohash)
for k,v in neighbors.items():
bits1 = v["bits"]
sl.add(bits1)
t1 = time.time()
print(t1-t0)
lonTest = 172.76843
latTest = 61.560745
geohashTest = geoHash.encode(lonTest,latTest,26)
bitsTest = geohashTest["bits"]
我想做的是以下
it = sl.irange(bitsTest-window,bitsTest+window)
我的问题是如何计算窗口?我希望窗口在0.1度以内或我指定的任何窗口内。我不知道如何计算窗口。整个geohash包非常快,我只对查询的近似匹配感兴趣。我相信我的测试点应该在我计算出地理哈希值的输入数据集的“范围内”,但我不知道如何获取查询点的地理哈希值范围。有人可以帮忙吗?
更新 提出的答案很好,但复杂度为O(N)。如果存在可接受的O(log N)阶数复杂度,则可以接受。
答案 0 :(得分:1)
听起来应该是可能的。您正在寻找0.1度精度。当然,以米为单位的多少取决于您在地球上的位置以及我们说的是经度还是纬度。但是你可以算出来。基于此,您可以找出ghehash的最小前缀是什么,以使其覆盖矩形即可。具有相同前缀的较长哈希值包含在较小前缀描述的矩形中。
为获得更好的粒度,请使用多个稍长的矩形。这也可以帮助您解决各种情况,无论您在看什么范围都越过矩形的边缘。
然后,如果要生成一组长度足够长的geohash,它们精确地覆盖了一个具有您要查找范围的原点的圆,那么范围查询就可以确定坐标的geohash是否共享长足够的前缀加上那套geohash。
您可能想签出我的https://github.com/jillesvangurp/geogeometry库。它具有以上所有功能的算法和功能。您可以制作圆,边界框或多边形,并使用给定最大长度的地理哈希覆盖那些。您可以使用另一个函数来计算该最大长度的合适值。
它是基于Java的,但根据我的结构,它应该可以轻松移植到python或您想要的其他任何东西。通常情况下,这只是循环和使用双打的简单数学运算。
六年前,我实际上使用它来实现一个简单的地理空间搜索引擎。如果您拥有可以处理数千万个geheohashes的数据库或搜索引擎,则可很好地进行扩展。对于较小的数据集,您可以轻松地在内存中执行此操作。