Solr 4.5:路线距离:排序或过滤

时间:2013-10-21 13:01:26

标签: solr solr4 spatial-query jts wkt

使用Solr 4.5和用例是我需要按照到给定路线的距离对结果进行排序。 使用包含1个地理坐标的文档作为rpt字段geo(感兴趣点的位置)。

以下是我的目标:http://i.imgur.com/lGgMEal.jpg。我想计算从文档到给定路线的最短距离,并将其用作增强组件。

目前的尝试是在{!score=recipDistance}模式下使用edismax函数,并在WKT中将路由描述作为LineString发送。这是现在发送的查询:

fl=*,score,distdeg:query({!score=distance filter=false v=$spatialfilter})
defType=edismax
q.alt=*:*
boost=query({!score=distance filter=false v=$spatialfilter})
spatialfilter=geo:"Intersects(LINESTRING (59.79619 11.38690, 60.25974 11.63869))"

以URI形式:

http://sokemotortest:8080/solr/collection1/select?fl=*%2Cscore%2Cdistdeg%3Aquery%28{!score%3Ddistance+filter%3Dfalse+v%3D%24spatialfilter}%29&wt=json&debugQuery=true&defType=edismax&q.alt=*%3A*&boost=query%28{!score=distance%20filter=false%20v=$spatialfilter}%29&spatialfilter=geo:%22Intersects%28LINESTRING%20%2859.79619%2011.38690,%2060.25974%2011.63869%29%29%22

我对这种方法的问题是:

  • 距离似乎是从形状(路线)的中心计算出来的。这意味着我们距离线路不远,而是距离现场。通过此查询,Pt(x=60.027965,y=11.512795)
  • 距离计算的结果似乎不对。索引中有4个文档,它们按以下顺序排列:

    • (1)59.7333,7.61283
    • (2)59.6236,10.7263
    • (3)59.6238,10.7385
    • (4)64.12379,22.14029

    当订单应该是:

    • (3)59.6238,10.7385
    • (2)59.6236,10.7263
    • (1)59.7333,7.61283
    • (4)64.12379,22.14029

您可以在此处查看boost calc debug的完整结果:pastebin.com/5tvCb0Cf

另一个有效的解决方案可能是按路径距离过滤文档(例如:http://i.imgur.com/EJu8Kcg.jpg)。这可以通过使用似乎在jTS和spatial4j中都支持的缓冲线来完成。唯一的问题是如何将缓冲行作为输入发送到Intersect函数(如下所示:geo:"Intersects(LINESTRING (59.79619 11.38690, 60.25974 11.63869) d=1)")。

这里的解决方案是创建一个自定义搜索组件,它将接受路由作为LineString,并将进一步转发,如Polygon或MuliPolygon,但我宁愿避免开发自定义组件,除非有必要。

我的问题是:

  • 在Solr 4.5中是否可以与LineString保持距离,而不是到形状的中心?
  • 我们可以发送缓冲行作为Intersect函数的输入(像这样:geo:"Intersects(LINESTRING (59.79619 11.38690, 60.25974 11.63869) d=1)")?

PS:索引中字段的描述:

<field name="geo" type="location_rpt" indexed="true" stored="true"/>

字段类型定义:

<fieldType name="location_rpt"
    class="solr.SpatialRecursivePrefixTreeFieldType"
    spatialContextFactory="com.spatial4j.core.context.jts.JtsSpatialContextFactory" 
    geo="true"
    distErrPct="0.025"
    maxDistErr="0.000009"
    units="degrees"
    />

1 个答案:

答案 0 :(得分:0)

  1. 无法(没有自定义Solr)从每个文档的索引点获取到查询LineString的距离。您将需要编写一个引用lineString的ValueSourceParser(您可以使用JTS WKT解析器进行解析)并且还引用您的索引点字段。为了在每个文档的基础上有效地从文档中检索点,请使用LatLonType,而不是RPT。 JTS可以计算点和LineString之间的距离,但请记住JTS在欧几里德空间中运行。为了获得更好的准确性,您需要将数据(索引点和lineString)“投影”到以lineString为中心的投影。 Proj4j可以提供帮助。

  2. RE bufferedLineStrings,您可能有兴趣知道Spatial4j的主分支具有“BufferedLineString”形状 - 它是Spatial4j的原生。但是,它还没有被整合到形状解析中,所以还没有完全准备好。为了清楚起见,它经过了很好的测试,并且我私下使用了非开源的解析器。这也是欧几里得空间有限,就像JTS一样。解决此问题的最佳方法是添加自己的Solr查询解析器(比听起来更容易)。此查询解析器将读取缓冲区距离,LineString,并从那里使用JTS来缓冲它。投影到形状的中心点是不可行的,因为它必须与索引数据对齐,因此您可以通过适当的量进行过度缓冲补偿,从而增加形状大小但至少确保捕获最小距离。我有计划更好地解决这个问题,但我一直很忙。