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. CSS之动态相册

    注释还是比较详细的,所以我就不一一再说明了.--->运行效果图<--- (点击之前温馨提示一下:此picture是我自己的照片,本来不想拿出来的,后来觉得反正不会有很多人看到而且也没人认识 ...

  2. jQuery download file

    jQuery.download = function (url, method, p, c, e, i, o, goodsType, reciveUser, suplier) { jQuery('&l ...

  3. phalcon 连接多个数据库 phalcon multi-database

    db: //This service returns a MySQL database $di->set('dbMaster', function() { return new \Phalcon ...

  4. Remoting 学习一调用远程的类就像调用本地的类一样

    Remoting   使用TCP/IP 协议,服务端可以是服务,web服务器,类.   例子1.  远程调用服务端的类,就像调用客户端机器上的类一样.   服务端代码 (先定义被客户端调用的类,然后注 ...

  5. android:descendantFocusability用法简析(转)

        开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题 ...

  6. Spring3.2.9 + JdbcTemplate 事务

    XML新增声明式事务配置 <!-- 事务管理器 --> <bean id="transactionManager" class="org.springf ...

  7. LeetCode OJ:Populating Next Right Pointers in Each Node II(指出每一个节点的下一个右侧节点II)

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  8. vue mint ui 手册文档对于墙的恐惧

    http://www.cnblogs.com/smallteeth/p/6901610.html npm 安装 推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用. npm ...

  9. BZOJ4808: 马

    BZOJ4808: 马 https://lydsy.com/JudgeOnline/problem.php?id=4808 分析: 黑白染色,求二分图最大匹配即可. 代码: #include < ...

  10. C++语言对C的增强(1)——实用性、变量检测、struct类型、C++中所有变量和函数都必须有类型、bool类型、三目运算符

    1.“实用性”增强 C语言中的变量都必须在作用域开始的位置定义,C++中更强调语言的“实用性”,所有的变量都可以在需要使用时再定义. 2.变量检测加强 在C语言中,重复定义多个同名的全局变量是合法的: ...