zoukankan      html  css  js  c++  java
  • Solr 空间搜索配置、按经纬度计算距离排序

    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:兴华南街)。
    
     
  • 相关阅读:
    tensorflow RNN和简单例子
    推荐系统理论及实战(转)附个人的理解和实战
    mysql 中 case when then .... else end 的简单使用
    动态规划最常见的习题 (最长公共子串、最长公共子序列、最短编辑距离)
    神经网络中 梯度消失、梯度爆炸的问题分析
    深度学习基础(转)
    用户兴趣的模型 浅析
    20190317 A
    pkuwc2019游记
    练习题16
  • 原文地址:https://www.cnblogs.com/tnsay/p/6089236.html
Copyright © 2011-2022 走看看