solr搜索最近距离的使用教程

论坛 期权论坛 脚本     
匿名技术用户   2020-12-29 03:45   11   0

说明:

solr4之后支持空间搜索。

它底层使用的时Bkd树,标准的临近搜索算法。

本文是教你怎么使用,其他不多赘述,只说如何做到以下两点:

1.距离45,94经纬度300km内的所有点,按升序排列,可分页。

2.距离45,94最近的点,按升序排列,可分页,并返回距离。

你需要先做一番工作:

配置:

我们新建一个名字叫geo的core,打开它的配置文件managed-schema,里面有这样一个叫做location的fieldType

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

接下来我们新建一个field,引入该fieldType.

<field name="loc" type="location" indexed="true"/>

你需要注意的是以下两点:

1.这个location实际上就是解析经纬度的。只要有field使用type=location,就意味着该field的值是“lat,lon”,即“纬度,经度”,比如“43.333,26.1122”;

2.loc我添加了indexed=true,该作用是将经纬度放到BKD树里,如果不使用indexed而是启用docValues=true时,纬度和经度对被比特交织成64位并放入Lucene DocValues,docValues数据的准确性约为1厘米。我还不能理解什么是比特交织,你也可能不会用到这段话,了解即可。

往里面添加数据:

此时因为geo——core里面有必填的id,以及我们设定的loc.

我用java添加数据的,添加了9999条数据:

添加的格式伪代码如下:

Random r = new Random();//随机数
for(i<<<10000){
    "id" = i+"_solr";
    //纬度范围是-90~90,经度范围-180~180
    "loc" = (r.nextInt(180)-90)+","+(r.nextInt(360)-180));

}

添加后的数据大约长这样:

准备工作做完了,开始搜索:

1.距离45,94经纬度300km内的所有点,按升序排列,可分页。

q=*:*&fq={!geofilt}&sfield=loc&pt=45,94&d=300&sort=geodist() asc&start=0&rows=5

红字是可以替换的,蓝字是分页.

此时结果就已经排序了.

例如:

http://localhost:8983/solr/geo/select?q=*:*&fq={!geofilt}&sfield=loc&pt=45,94&d=1000&sort=geodist()%20asc&start=1&rows=5

%20是空格的URL编码

结果:

2.距离45,94最近的点,按升序排列,可分页,并返回距离。

&q={!func}geodist()&sfield=loc&pt=45,94&sort=score+asc&fl=*,score

直接上结果:

可以看到效率很高的.

这两个功能一般都足够使用了.教程至此结束.

2019.4.18

有同学更复杂的不好写,java代码粘出来,大致如下:

/**
  * 搜索最近距离的商品,附带条件商品标题关键字和类型 条件
  * @param keyword 商品标题关键字
  * @param type 类型
  * @param pt 坐标点
  * @param page 分页
  * @param rows 分页
  * @return
  */
 public SolrDocumentList queryDonations(String keyword, Integer type,String pt,  int page, int rows){
  /**
   * 创建query对象
   */
  SolrQuery query = new SolrQuery();
  query.setQuery("{!func}geodist()");
  query.setSort("score ", SolrQuery.ORDER.asc);
  query.addField("*,score");
  query.setStart((page - 1) * rows);
  query.setRows(rows);
  Map<String, String> map = new HashMap<>();
  map.put("sfield", "loc");//loc是solr坐标字段
  map.put("pt", pt);//中心坐标条件
  SolrParams arg0 = new MapSolrParams(map);
  query.add(arg0);
  
  /**
   * keyword条件 和type条件
   */
  if (!StringUtils.isBlank(keyword)) {
   query.addFilterQuery("title:" + "\"" + keyword + "\"");
  }
  if (type != null) {
   query.addFilterQuery("type:" + type);
  }
  ....//执行查询
  ....
 }

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP