Solr 空间搜索配置

1.          在solr目录下的找到conf文件夹下的schema.xml.

       <fields>   

            <!-- 在fields元素中添加如下代码 -->   

            <field name="store_lat_lon" type="location" indexed="true" stored="true"/>

            <dynamicField name="*_coordinate" type="double" indexed="true" stored="false" multiValued="false"/>

      </fields>

2.          在solr目录下的找到conf文件夹下的db-data.config.xml .

    把dataConfig标签内的script标签的内容做如下修改。

    <script><![CDATA[

                function f1(row){

                    row.put('$docBoost', 1);

                    var lat_coordinate = row.get("GPS_Y ");

                    var log_coordinate = row.get("GPS_X ");

                    if( lat_coordinate != null &&  log_coordinate != null ){

                      if(  lat_coordinate*1 >= -90  &&  lat_coordinate*1 <= 90 ) {

                             var store_lat_lon = lat_coordinate + "," + log_coordinate;

                                 var arr = new java.util.ArrayList()

                                 arr.add(lat_coordinate);

                                 arr.add(log_coordinate);

                                 row.put("store_lat_lon",store_lat_lon);

                                 row.put("item",arr);     

                          }              

                    }

                    return row;

                }

        ]]></script>

3.       重新启动solr. 

    重建索引:http://localhost:8080/solr/dataimport?command=full-import 

4.          查询示例:

http://localhost:8080/solr/select/?q=*:*&fq={!geofilt}&sfield=store_lat_lon&pt=86.13909901,41.770741&d=5&fl=name,gps_x,gps_y,store_lat_lon&sort=geodist() asc

参数

描述

示例

d

距离(单位:km)

&d=10.0

pt

搜索过滤的中心点,纬度,经度坐标点

&pt=33.4,29.0

sfield

空间搜索类型的字段(eg: solr.LatLonType)

&sfield=store_lat_lon

fq

设置查询过滤器

fq={!geofilt}

sort

根据字段或者函数排序

&sort=geodist() asc

geofilt 函数:  使结果集约束在到中心点位置的最大距离(km)圆形区域内。

geodist 函数:   计算两点之间的距离。

注意:solr 3.4版本以上才支持geodist等空间搜索函数。

参考:http://wiki.apache.org/solr/SpatialSearch

Script形式的转换只在JDK1.6版本或以上才支持,下面是通用的空间搜索转换的实现,支持JDK1.5及其以上版本。

新建一个类如下所示,该类可以不继承或实现任何其他接口或者抽象类,但是transformRow方法必须定义成下面所示,SOLR dataimport插件会通过反射的方式去调用这个方法。

package com.besttone.transformer;

import java.util.ArrayList;

import java.util.Map;

public class LocationTransformer {

       // 参考资料 http://wiki.apache.org/solr/DIHCustomTransformer

       public Object transformRow(Map<String, Object> row) {

              // TODO Auto-generated method stub

              row.put("$docBoost", 1);

              Object lat_coordinate = row.get("GPS_Y");

              Object log_coordinate = row.get("GPS_X");

              if (lat_coordinate != null && log_coordinate != null) {

                     if (Double.parseDouble(lat_coordinate.toString()) * 1 >= -90

                                   && Double.parseDouble(lat_coordinate.toString()) * 1 <= 90) {

                            String store_lat_lon = lat_coordinate.toString() + ","

                                          + log_coordinate.toString();

                            ArrayList arr = new ArrayList();

                            arr.add(lat_coordinate);

                            arr.add(log_coordinate);

                            row.put("store_lat_lon", store_lat_lon);

                            row.put("item", arr);

                     }

              }

              return row;

       }

}

第二步在db-data-config.xml中的entity节点上配置转换类:

<entity name="zbs" transformer="com.besttone.transformer.LocationTransformer"  ………..

这个类必须以全路径配置。

第三步将上面的类用jdk1.5编译并打成JAR包,放在solr/home的lib下面,然后再solr.xml中配置全局共享lib:

<solr persistent="false" sharedLib="lib">

这样dataimport就能找到这个转换类,并通过反射的方式调用transformRow实现转换.

也可以继承Transformer抽象类来实现更高级的自定义转换类应用。

参考资料 http://wiki.apache.org/solr/DIHCustomTransformer

若要返回距离,4.0版本可以参照第一种方法,4.0以下版本可参照下面第二种方法,score返回的就是距离。

Returning the distance

<!>Solr4.0

You can use the pseudo-field feature to return the distance along with the stored fields of each document by addingfl=geodist() to the request. Use an alias like fl=_dist_:geodist() to make the distance come back in the_dist_ pseudo-field instead. Here is an example of sorting by distance ascending and returning the distance for each document in_dist_.

...&q=*:*&sfield=store&pt=45.15,-93.85&sort=geodist() asc&fl=_dist_:geodist()

As a temporary workaround for older Solr versions, it's possible to obtain distances by using geodist or geofilt as the only scoring part of the main query.

...&sfield=store&pt=45.15,-93.85&sort=score%20asc&q={!func}geodist()

若要显示距离并按某些字段比如名字来查询的话,那查询条件只能写在fq中,如果写在q中则会影响得分,导致score字段返回的不是距离,写法如下:

http://localhost:8089/solr/select/?q={!func}geodist()&fq={!geofilt}&fq=address:兴华南街&sfield=store_lat_lon&pt=41.78101895,123.36067849&d=5&sort=score%20asc&fl=score

查找5公里范围内并且地址在兴华南街的数据(fq=address:兴华南街)。

Solr 空间搜索配置、按经纬度计算距离排序的更多相关文章

  1. mysql使用sql语句根据经纬度计算距离排序

    CREATE TABLE `locationpoint` ( `id` int(11) NOT NULL, `province` varchar(20) NOT NULL, `city` varcha ...

  2. iOS根据2个经纬度计算距离

    #pragma mark - calculate distance 根据2个经纬度计算距离 #define PI 3.14159265358979323 +(double) CalculationDi ...

  3. java工具类(六)根据经纬度计算距离

    Java实现根据经纬度计算距离 在项目开发过程中,需要根据两地经纬度坐标计算两地间距离,所用的工具类如下: Demo1: public static double getDistatce(double ...

  4. python的N个小功能(文本字段对应数值,经纬度计算距离,两个时间点计算时间间隔)

    案例1 >>> import pandas as pd >>> df=pd.DataFrame({'A':[1,2,3],'B':[1,2,3],'C':[1,2, ...

  5. php有经纬度计算距离

    /** *  @desc 根据两点间的经纬度计算距离 *  @param float $lat 纬度值 *  @param float $lng 经度值 */  function getDistanc ...

  6. PHP根据两点间的经纬度计算距离,php两点经纬度计算(转)

    这是一个不错的示例,直接贴代码,首先要知道纬度值.经度值 /** * @desc 根据两点间的经纬度计算距离 * @param float $lat 纬度值 * @param float $lng 经 ...

  7. MySQL创建根据经纬度计算距离的函数

    按照经纬度计算距离 日常开发中,特别是做微信项目时,经常会遇到根据用户地理位置来展示附近商家的功能,通常解决这种问题的思路是,后台设置商家的经纬度,然后再根据前台传的经纬度进行计算,具体经纬度转换以及 ...

  8. PHP根据两点间的经纬度计算距离

    /** * 说明: 根据两点间的经纬度计算距离 * @param float $lat 纬度值 * @param float $lng 经度值 */ function getDistance($lat ...

  9. cesium根据经纬度计算距离

    var startLatitude = 36;var startLongitude = 120; var endLatitude=34; var endLongitude=121; var start ...

随机推荐

  1. 保护SSH的三把锁

    ///////////////////////////////写在前面//////////////////////////////////////原帖地址:http://www.ibm.com/dev ...

  2. JDBC方式操作数据库

    1.读取配置文件,我将配置信息写入配置文件(.properties)中,方便后期数据库变更后或者其他项目使用,扩展性好些,尽量避免硬编码. driver=oracle.jdbc.driver.Orac ...

  3. ios 获取导航栏和状态栏高度,针对iPhoneX

    因为iPhoneX的产生,原本的导航栏再也不是44了,那么会出现什么问题呢?在隐藏导航栏的页面,原本的高度要向上调整一个导航栏+状态栏的高度.那么iPhoneX的导航栏高度不是44了,我们需要手动获取 ...

  4. NSObject头文件解析 / 消息机制 / Runtime解读 (二)

    本章接着NSObject头文件解析 / 消息机制 / Runtime解读(一)写 给类添加属性: BOOL class_addProperty(Class cls, const char *name, ...

  5. hive_异常_01_ Terminal initialization failed; falling back to unsupported

    一.异常现象 hive初始化数据库时,在执行了 schematool -initSchema -dbType mysql 这个命令时,终端抛出如下异常: [ray@rayner bin]$ schem ...

  6. luogu 3375 KMP模板题

    #include<bits/stdc++.h> using namespace std; ,M = ; int next[N]; void getNext(char s[]) //找nex ...

  7. OpenCV-Python在图片上输出中文

    OpenCV中在图片上输出中文一般需要借助FreeType库实现.FreeType库是一个完全免费(开源)的.高质量的且可移植的字体引擎,它提供统一的接口来访问多种字体格式文件.但使用FreeType ...

  8. Linux命令学习(22):ss命令

    版权声明 更新:2017-05-20 博主:LuckyAlan 联系:liuwenvip163@163.com 声明:吃水不忘挖井人,转载请注明出处! 1 文章介绍 本文介绍了Linux下面的ss命令 ...

  9. 循环比赛日程表(match)(分治)

    [问题描述]     设有N个选手进行循环比赛,其中N=2M,要求每名选手要与其他N-1名选手都赛一次,每名选手每天比赛一次,循环赛共进行N-1天,要求每天没有选手轮空.     输入:M     输 ...

  10. django的工作图