gpt4 book ai didi

java - Lucene 空间、准确性

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:23:01 28 4
gpt4 key购买 nike

我正在遵循“Lucene in Action”中的示例,第 308-315 页,它描述了 Lucene Spatial。我正在使用 lucene 2.9.4。我用过 http://geocoder.us/service/distance endpoint 来计算一些位置之间的距离,然后编写单元测试来验证索引可以找到给定半径内的位置。

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

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

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

编辑:我还发现了这个:https://issues.apache.org/jira/browse/LUCENE-2519和这里明显固定的代码:http://code.google.com/p/spatial-search-lucene/source/browse/trunk/src/main/java/org/apache/lucene/spatial/tier/projection/SinusoidalProjector.java?r=38 ,但是当我修补我的代码以使用固定的 SinusoidalProjector 时,我的索引在所有情况下都返回零广告。

这并没有给我很大的信心:

http://www.lucidimagination.com/blog/2010/07/20/update-spatial-search-in-apache-lucene-and-solr/

http://www.lucidimagination.com/search/document/c32e81783642df47/spatial_rethinking_cartesian_tiers_implementation#c32e81783642df47

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

最佳答案

我花了一些时间查看源代码,我想我明白出了什么问题。首先,我做了一个错误的假设,即由 geocoder.us 计算的距离与 lucene 内部计算的点间距离相同。这些值很接近,但不精确。所以我转而通过调用 lucene 来计算纬度/经度对之间的距离

double distance = DistanceUtils.getInstance().getDistanceMi(lat1,lon1,lat2,lon2);

接下来我深入研究了 DistanceQueryBuilder 类 http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-spatial/2.9.4/org/apache/lucene/spatial/tier/DistanceQueryBuilder.java?av=f ,我认为它有一个错误。

它计算边界框是为了像这样获取笛卡尔层:

CartesianPolyFilterBuilder cpf = new CartesianPolyFilterBuilder(tierFieldPrefix);
Filter cartesianFilter = cpf.getBoundingArea(lat, lng, miles);

通过查看 LLRect.createBox http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-spatial/2.9.4/org/apache/lucene/spatial/geometry/shape/LLRect.java#LLRect.createBox%28org.apache.lucene.spatial.geometry.LatLng%2Cdouble%2Cdouble%29 就很清楚了getBoudningArea 的第三个参数将被视为边界框的完整宽度/高度。因此传递半径值会导致边界框太小。

解决方法是提供一个替代版本的 DistanceQueryBuilder 来执行此操作:

Filter cartesianFilter = cpf.getBoundingArea(lat,lng,miles*2);

这似乎有效。我仍然相信 DistanceApproximation http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-spatial/2.9.4/org/apache/lucene/spatial/geometry/shape/DistanceApproximation.java#DistanceApproximation.getMilesPerLngDeg%28double%29虽然被打破了,因为看起来以下操作应该是可逆的,但它们不是:

// 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 时(而不是断言我只是打印结果),我得到:

Lng delta: 0.36142327178505024, dist: 20.725929003138496
Lat delta: 0.4359569489852007, dist: 30.155567734407825

我猜测代码之所以有效,只是因为在选择边界框后选择的笛卡尔层会导致区域比边界框大一些。但我不认为这会得到保证。

我希望对此有更多了解的人可以发表评论,因为这些只是在挖掘代码一个下午后的观察结果。我确实注意到 lucene spatial 的最新代码在 googlecode 上看起来像:http://code.google.com/p/spatial-search-lucene/ , 似乎实现发生了重大变化,但我没有深入挖掘细节。

关于java - Lucene 空间、准确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6667672/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com