基于Solr空间搜索

概括:

     最近一个项目需要基于LBS查询附近的商铺信息,看了一下网上都是基于Solr和ELS方式来实现, 本来想使用ELS来实现的,但是由于项目以前用的是Solr, 所以就去调研了一下基于Solr来实现地理位置的搜索,并且在实现的时候整理了一下实现的笔记。       

    在开发中如果需要对带经纬度的数据进行检索,比如查找当前所在位置附近1000米的,一种简单的方法就是:获取数据库中的所有酒店数据,按经纬度计算距离,返回距离小于1000米的数据。

   这种方式在数据量小的时候比较有效,但是当数据量大的时候,检索的效率是会十分十分低的,本文介绍使用Solr的Spatial Query进行空间搜索。本文简述基于Solr实现空间范围搜索

基于Mysql 实现地理位置排序:

例如:

公式如下,单位米:

第一点经纬度:lng1 lat1

第二点经纬度:lng2 lat2

      round(6378.138*2*asin(sqrt(pow(sin( (lat1*pi()/180-lat2*pi()/180)/2),2)+cos(lat1*pi()/180)*cos(lat2*pi()/180)* pow(sin( (lng1*pi()/180-lng2*pi()/180)/2),2)))*1000) 

例如:

    SELECT    store_id,lng,lat, ROUND(6378.138*2*ASIN(SQRT(POW(SIN((22.299439*PI()/180-      lat*PI()/180)/2),2)+COS(22.299439*PI()/180)*COS(lat*PI()/180)*POW(SIN((114.173881*PI()/180-lng*PI()/180)/2),2)))*1000) AS juli  FROM store_info

ORDER BY juli DESC
LIMIT 316

基于Solr实现地理位置排序:

没学过的Solr 这里有一份官网手册: 

 http://lucene.apache.org/solr/guide/6_6/spatial-search.html


原理:

   具体的空间搜索原理和算法不多介绍,空间搜索算法都是很成熟的

     https://www.cnblogs.com/hanhuibing/articles/5680616.html

    https://www.cnblogs.com/keleyu/p/4993039.html

基于Solr的空间搜索实战:

   Solr已经提供了3种filedType来进行空间搜索:

  有四种可用于空间搜索的主要字段类型:

LatLonPointSpatialField

LatLonType (现已弃用)及其非大地双胞胎 PointType

SpatialRecursivePrefixTreeFieldType(简称RPT),包括RptWithGeometrySpatialField衍生产品

BBoxField


LatLonPointSpatialField是经纬度点数据最常见使用情况的理想字段类型。它取代了为了向后兼容而仍然存在的LatLonType。RPT提供了更多高级/自定义用例以及诸如多边形和热图等选项的更多功能。

RptWithGeometrySpatialField用于索引和搜索非点数据,尽管它也可以做点。它不能做排序/提升。

BBoxField 用于索引边界框,通过框查询,指定搜索谓词(相交,内部,包含,不相交,等于)以及相关性排序/提升类似overlapRatio或简单区域。

LatLonPointSpatialField  

  <fieldType name="location" class="solr.LatLonPointSpatialField" docValues="true"/>

   Indexing Points使用(x y) 或者(lat,lon) 格式进行保存;不然会报错

image.png

   用于地理空间搜索的空间Solr“查询分析器”:geofilt和bbox

geofilt

    该geofilt过滤器允许您根据给定点的地理空间距离(也称为“大圆距离”)检索结果。另一种看待它的方式是创建一个圆形滤镜。例如,要查找给定纬度/经度点五公里内的所有文件,可以输入。该过滤器返回给定半径的圆周内的所有结果:

   &q=:&fq={!geofilt sfield=store}&pt=45.15,-93.85&d=5

   image.png


bbox

该bbox过滤器与geofilt使用计算的圆的边界框非常相似。请参阅下图中的蓝色框。它采用与geofilt相同的参数。

以下是一个示例查询:

  &q=:&fq={!bbox sfield=store}&pt=45.15,-93.85&d=5


 矩形形状的计算速度更快,所以它有时可以用来替代geofilt返回半径之外的点的可接受范围。但是,如果理想目标是一个圆圈,但您希望它运行得更快,那么请考虑使用RPT字段并尝试一个较大的distErrPct值0.1(如10%半径)。这将返回半径之外的结果,但它将在形状周围有点均匀。

image.png

   当边界框包含一个极点时,边界框最终成为一个“边界盆”(球冠),如果边界框接触北极(或最高纬度的南部,如果有),则该边界包括圆的最低纬度以北的所有值它接触南极)。

通过任意矩形进行过滤

     有时,空间搜索要求要求在矩形区域中查找所有内容,例如用户正在查看的地图所覆盖的区域。对于这种情况,geofilt和bbox不会剪切它。这是一个窍门,但是你可以使用Solr的范围查询语法来提供左下角作为范围的开始和右上角作为范围的结束。

这是一个例子:

   &q=:&fq=store:[45,-94 TO 46,-93]

优化:缓存与否

将空间查询放入“fq”参数中是最常见的过滤器查询。默认情况下,Solr会将查询缓存在过滤器缓存中。

如果您知道过滤器查询(无论是否为空间)是相当独特的,并且不太可能获得缓存命中,则指定cache="false"为本地参数,如以下示例中所示

     &q=…mykeywords…&fq=…someotherfilters…&fq={!geofilt cache=false}&sfield=store&pt=45.15,-93.85&d=5


距离排序或提升(函数查询)

有四个距离函数查询:

geodist,见下文,通常是最合适的;

dist计算多维向量之间的p范数距离;

hsin,计算球体上两点之间的距离;

sqedist,来计算两点之间的平方欧几里德距离。

有关这些功能的查询的详细信息,请参阅该部分功能查询


geodist

    geodist是一个距离函数,需要三个可选参数:(sfield,latitude,longitude)。您可以使用该geodist功能按距离或得分返回结果对结果进行排序。

例如,要按距离递增对结果进行排序,请输入。&q=:&fq={!geofilt}&sfield=store&pt=45.15,-93.85&d=50&sort=geodist() asc

      要将距离作为文档分数返回,请输入&q={!func}geodist()&sfield=store&pt=45.15,-93.85&sort=score+asc。

更多示例

以下是一些您可以在Solr中进行空间搜索的更有用的示例。

1) 按距离排序,距离越近排名越高,加上score=distance,其中distance是索引点到坐标点之间的弧度值,系统根据弧度值排序。

    &fl=*,score&sort=score asc&q={!geofilt score=distance sfield=poi_location_p pt=54.729696,-98.52539

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值