solr经纬度坐标查询

     最近项目中使用到了solr,并且需求中需要通过给定一个经纬度,查询附件方圆多少多少范围的店铺信息,网上查了一下资料,大致总结了一下有几种使用方式

    1.使用LatLonType(用于平面坐标,而不是大地坐标)版本比较老 好像不怎么用了 

    2.SpatialRecursivePrefixTreeFieldType(缩写为RPT)  我用的就是这个 下面主要讲这个部分

    3.BBoxField(用于边界索引查询)  没用这个 具体的还不太了解

    因为我主要使用的是第2种方式来做的 所以主要写第2种方式RPT  

    首先的话需要在solr的配置文件中加上经纬度的配置 比如我的经纬度起的名称叫latitude_longitude  那么在配置中就需要加上这个的配置  

 这里的type类型为location_rpt  然后下面的class引用就是我们的第2种-——SpatialRecursivePrefixTreeFieldType

对solr.SpatialRecursivePrefixTreeFieldType的配置说明:

SpatialRecursivePrefixTreeFieldType

用于深度遍历前缀树的FieldType,主要用于获得基于Lucene中的RecursivePrefixTreeStrategy。

geo

默认为true,值为true的情况下坐标基于球面坐标系,采用Geohash的方式;值为false的情况下坐标基于2D平面的坐标系,采用Euclidean/Cartesian的方式。

distErrPct

定义非Point图形的精度,范围在0-0.5之间。该值决定了非Point的图形索引或查询时的level(如geohash模式时就是geohash编码的长度)。当为0时取maxLevels,即精度最大,精度越大将花费更多的空间和时间去建索引。

maxDistErr/maxLevels:maxDistErr

定义了索引数据的最高层maxLevels,上述定义为0.000009,根据 GeohashUtils.lookupHashLenForWidthHeight(0.000009, 0.000009)算出编码长度为11位,精度在1米左右,直接决定了Point索引的term数。maxLevels优先级高于maxDistErr, 即有maxLevels的话maxDistErr失效。详见SpatialPrefixTreeFactory.init()方法。不过一般使用 maxDistErr。

units

单位是degrees。

 

     接下来经纬度的数据从数据库读取出来 会有一个精度和一个纬度的字段,而在solr当中我们需要把这2个字段组合在一起 可以使用2种表达方式  比如114.31,30.52 或者114.31 30.52  一种是使用逗号隔开,另一种是使用空格的方式隔开 这里要记住一点 精度和纬度不要弄反了 不然会报错的  我之前就是因为把这2个值组合在一起写反了 然后报的异常信息:

Can't parse point '30.570000 114.020000' because: Bad Y value 114.02 is not in boundary Rect(minX=-180.0,maxX=180.0,minY=-90.0,maxY=90.0)

报错也非常的明显 就是超出了正常范围的值。所以在这里提一个醒 注意一下就行了。

    solr经纬度坐标查询_第1张图片

     这里使用“经度 纬度”这样的字符串格式将经纬度索引添加到latitude_longitude字段中  注意一点的是 如果你是先在solr中加入这个field的话 它会自动添加该字段的 然后类型为string 然后你再手动添加的话就会出现2个 运行的时候会报重复的字段值 所以如果有2个的话就需要删除一个 field不能重复  就把自动生成为string的删除掉 当然如果你正常先走第一步的话就不会出现这样的问题。

     最后查询的话 给几个例子吧 这样的查询百度一搜一大堆:

    q={!geofilt pt=45.15,-93.85 sfield=poi_location_p d=5 score=distance}

    q={!bbox pt=45.15,-93.85 sfield=poi_location_p d=5 score=distance}

    q=poi_location_p:"Intersects(-74.093 41.042 -69.347 44.558)" //a bounding box (not in WKT)

    q=poi_location_p:"Intersects(POLYGON((-10 30, -40 40, -10 -20, 40 20, 0 0, -10 30)))" //a WKT example

    涉及到的字段说明:

字段

含义

q

查询条件,如 q=poi_id:134567

fq

过滤条件,如 fq=store_name:农业

fl

返回字段,如fl=poi_id,store_name

pt

坐标点,如pt=54.729696,-98.525391

d

搜索半径,如 d=10表示10km范围内

sfield

指定坐标索引字段,如sfield=geo

defType

指定查询类型可以取 dismax和edismax,edismax支持boost函数相乘作用,dismax是通过累加方式计算最后的score.

qf

指定权重字段:qf=store_name^10+poi_location_p^5

score

排序字段根据qf定义的字段defType定义的方式计算得到score排序输出

     在程序当中的话 则是:

       if(latitude!=null&&longitude!=null) {

            query.set("q",keyword);
            query.set("fq", "{!geofilt}");        //距离过滤函数
            query.set("pt", longitude+" "+latitude); //当前经纬度
            query.set("sfield", "latitude_longitude"); //经纬度的字段
            query.set("d", 5+""); //就近 5 km的所有数据
            query.set("sort", "geodist() asc"); //距离排序

            query.set("fl","*,dist:geodist()");//返回的距离数据  
        }

整个过程大致就是酱紫的 因为这里我只使用到了第2种搜索经纬度的方式,第1和第3种的还没有用到 所以就主要就第2种rpt的方式来写的。

 

  solr经纬度坐标查询_第2张图片

你可能感兴趣的:(个人功能模块开发,solr)