Java Lucene空间,精确

Java Lucene空间,精确,java,lucene,Java,Lucene,我遵循“Lucene in Action”(第308-315页)中的示例,该示例描述了Lucene Spatial。我用的是lucene 2.9.4。我使用endpoint来计算一些位置之间的距离,然后编写单元测试来验证索引是否可以找到给定半径内的位置 我想知道我能期望lucene有多准确。例如,如果我给半径10.0,我的lat/lon点之间的距离是9.99英里,它在所有情况下都能找到这个位置吗 提示这个问题的是,我发现搜索对于小半径值(例如10.0或更小)非常准确,而对于较大的值(例如r=25

我遵循“Lucene in Action”(第308-315页)中的示例,该示例描述了Lucene Spatial。我用的是lucene 2.9.4。我使用endpoint来计算一些位置之间的距离,然后编写单元测试来验证索引是否可以找到给定半径内的位置

我想知道我能期望lucene有多准确。例如,如果我给半径10.0,我的lat/lon点之间的距离是9.99英里,它在所有情况下都能找到这个位置吗

提示这个问题的是,我发现搜索对于小半径值(例如10.0或更小)非常准确,而对于较大的值(例如r=25.0)则不准确

有什么我可能做错的吗?搜索者是否可能选择一个没有给定半径的所有横向/纵向的层?我的理解是,它选择了保证所有点都在半径内的最小层,即层算法只是一种优化

编辑: 我还发现:这里的代码显然是固定的:,但当我修补代码使用固定的正弦投影时,我的索引在所有情况下都返回零广告

这并没有给我多少信心:


这似乎表明整个代码中都存在黑客行为,仅仅修补SinusoidalProjector是不够的。

我花了一些时间研究了源代码,我想我了解出了什么问题。首先,我做了一个错误的假设,即geocoder.us计算的距离与lucene内部计算的点间距离相同。数值接近,但不精确。所以我转而通过调用lucene的来计算lat/lon对之间的距离

double distance = DistanceUtils.getInstance().getDistanceMi(lat1,lon1,lat2,lon2);
接下来我深入研究了DistanceQueryBuilder类,我认为它有一个bug

它计算边界框以获取笛卡尔层,如下所示:

CartesianPolyFilterBuilder cpf = new CartesianPolyFilterBuilder(tierFieldPrefix);
Filter cartesianFilter = cpf.getBoundingArea(lat, lng, miles);
通过查看LLRect.createBox,很明显getBoudningArea的第三个参数将被视为边界框的全宽/全高。因此,传递半径值会导致边界框太小

修复方法是提供一个替代版本的DistanceQueryBuilder,用于:

Filter cartesianFilter = cpf.getBoundingArea(lat,lng,miles*2);
这似乎有效。但我仍然相信距离近似是被打破的,因为以下操作似乎应该是可逆的,而它们不是:

// similar to implementation of DistanceUtils.getBoundary():
double milesPerLng = DistanceApproximation.getMilesPerLngDeg(lat);
double milesPerLat = DistanceApproximation.getMilesperLatDeg();


double lngDelta = radius / milesPerLng;
double latDelta = radius / milesPerLat;

// Now it seems like this should be roughly true:
assertEquals(radius, DistanceUtils.getInstance().getDistanceMi(lat,lng,lat,lng+lngDelta));
assertEquals(radius, DistanceUtils.getInstance().getDistanceMi(lat,lng,lat+latDelta,lng));
但事实并非如此。例如,当上面的代码给定lat=34、lng=-118和radius=25时(而不是断言我只是打印结果),我得到:

我猜代码之所以有效,是因为拾取边界框后选择的笛卡尔层将导致比边界框稍大的区域。但我认为这不能保证


我希望对此有更多了解的人可以发表评论,因为这些只是在深入研究代码一个下午后的观察结果。我确实注意到,lucene spatial的最新代码似乎出现在Google代码上:,而且实现似乎有了很大的变化,但我没有深入挖掘细节。

他们在lucene 3.5.0中修复了这一问题。现在大距离和小距离都可以使用

Lucene 4 spatial确实是基于它的,而且它有很大的不同。我建议你升级到Lucene 4。v3中的空间模块有很多缺陷/不可信,而且没有维护,所以被丢弃了。谢谢……我不再在同一家公司工作了,但我正在使用solr 4进行我当前工作的一个项目。
Lng delta: 0.36142327178505024, dist: 20.725929003138496
Lat delta: 0.4359569489852007, dist: 30.155567734407825