1. 程式人生 > >基於Solr空間搜尋

基於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 這裡有一份官網手冊: 

原理:

   具體的空間搜尋原理和演算法不多介紹,空間搜尋演算法都是很成熟的

基於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.525391 d=10}。

2) 按距離排序,距離越遠排名越高,加上score=reciDistance,其中reciDistance 範圍是0~1 採用倒數的方式計算,故與distance的排序剛好相反

    &fl=*,score&sort=score asc&q={!geofilt score=reciDistance sfield=poi_location_p pt=54.729696,-98.525391 d=10}

3) 距離僅作排序不做過濾,在條件中設定filter=false,其中d只是確定形狀的作用,不起限制作用。

     &fl=*,score&sort=score asc&q={!geofilt score=distance filter=false sfield=poi_location_p pt=54.729696,-98.525391 d=10}

4) 結合關鍵詞查詢和距離排序,此時關鍵字只能作為過濾條件(fq)不能作為查詢條件,僅作為過濾域。

&fl=*,score& fq=store_name:農業&sort=score asc&q={!geofilt score=distance sfield=poi_location_p pt=54.729696,-98.525391 d=10}

5) 當關鍵字和距離都作為排序條件時,可以用qf引數設定權重

&fl=*,score& fq=store_name:農業&sort=score asc&q={!geofilt score=distance sfield=poi_location_p pt=54.729696,-98.525391

SpatialRecursivePrefixTreeFieldType:

本文重點介紹使用SpatialRecursivePrefixTreeFieldType,不僅可以用點,也可以用於多邊形的查詢。

1、配置Solr

個人使用的solr6.6.2:

<fieldType name="location_rpt"   class="solr.SpatialRecursivePrefixTreeFieldType"
               spatialContextFactory="org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory"
               autoIndex="true"
               validationRule="repairBuffer0"
               distErrPct="0.025"
               maxDistErr="0.001"
               distanceUnits="kilometers"  />

<field name="station_position" type="location_rpt" indexed="true" stored="true" multiValued="false" />

對solr.SpatialRecursivePrefixTreeFieldType的配置說明:SpatialRecursivePrefixTreeFieldType

用於深度遍歷字首樹的FieldType,主要用於獲得基於Lucene中的RecursivePrefixTreeStrategy。

geo

預設為true,值為true的情況下座標基於球面座標系,採用Geohash的方式;值為false的情況下座標基於2D平面的座標系,採用Euclidean/Cartesian的方式。

distErrPct

    定義非Point圖形的精度,範圍在0-0.5之間。該值決定了非Point的圖形索引或查詢時的level(如geohash模式時就是geohash編碼的長度)。當為0時取maxLevels,即精度最大,精度越大將花費更多的空間和時間去建索引。

maxDistErr/maxLevels:maxDistErr

      定義了索引資料的最高層maxLevels,上述定義為0.000009,根據 GeohashUtils.lookupHashLenForWidthHeight(0.000009, 0.000009)算出編碼長度為11位,精度在1米左右,直接決定了Point索引的term數。maxLevels優先順序高於maxDistErr, 即有maxLevels的話maxDistErr失效。詳見SpatialPrefixTreeFactory.init()方法。不過一般使用 maxDistErr。

distanceUnits 單位是degrees(度) 

worldBounds
       世界座標值:”minX minY maxX maxY”。 geo=true即geohash模式時,該值預設為”-180 -90 180 90”。geo=false即quad時,該值為Java double型別的正負邊界,此時需要指定該值,設定成”-180 -90 180 90”。

實戰程式碼:

public class SolrGEO {
 
       public static void main(String[] args) {
 
              /*SolrQuery solrQuery = new SolrQuery();
 
              solrQuery.set("d", value + ""); // 搜尋半徑
 
              solrQuery.set("sfield", CommonConst.LOCATION_FIELD);// 儲存地理位置的欄位名稱
 
              solrQuery.set("pt", searchContent.getShopLocation()); // 經緯度引數格式為 緯度,經度
 
              solrQuery.set("fl", "*,distance:geodist()"); // 文件中用distance表示距離欄位
 
              solrQuery.addSort("geodist()", ORDER.asc);// 按照從近到遠排序
*/
              
              
              
              //addIndex();
              queryIndex();
              
       }
       
       public static void queryIndex() {
              try {
                     HttpSolrClient server = SolrServer.getServer();
                     
                     SolrQuery params=new SolrQuery();   
                  /*params.setParam("q", "{!geofilt score=distance filter=false sfield=station_position pt=23.104487,113.375981 d=1}");
                  params.addSort("score",ORDER.asc);*/
                  
                     params.setParam("q","*:*");
                     params.setParam("start", "0");//記錄開始位置    
               params.setParam("rows", "10");//查詢的行數    
               params.set("fq", "{!geofilt}");           //距離過濾函式
               params.set("pt", "23.104487,113.375981"); //當前經緯度
               params.set("sfield", "station_position"); //經緯度的欄位
               params.set("d", "1"); //就近 d 20km的所有資料
               params.set("score", "distance"); 
               params.addSort("geodist()",ORDER.asc);//按照從近到遠排序
             
               /**
                * geofilt :  //距離過濾函式    “大圓距離”)檢索結果
                * sfield : 座標欄位
                * d :  空間範圍 公里 預設使用單位為千米(1km=0.009度)
                */
             /*  String query=" {!geofilt score=distance sfield=station_position  d=1 }  ";  
               params.addFilterQuery(query);   */  
               
               QueryResponse resp = server.query(params);   
               
               System.out.println(params.toQueryString());
               
               SolrDocumentList docs = resp.getResults();    
               for(int i=0;i<docs.size();i++){    
                   SolrDocument sid=docs.get(i);  
                   
                            String title = (String) sid.getFieldValue("title");
                            System.out.println(title);
                   String station_position= (String) sid.getFieldValue("station_position");
                   String [] positions=station_position.split(",");
                   double lat2=  Double.valueOf(positions[0]);  
                double lng2 = Double.valueOf(positions[1]);
                double range=getDistance(23.104487d,113.375981d,lat2,lng2);
                System.out.println("與當前座標距離:"+range);
                   System.out.println(sid);    
               }    
              } catch (Exception e) {
                     e.printStackTrace();
              }
              
       }
 
   private static double EARTH_RADIUS = 6378.137;    
    
    private static double rad(double d) {    
        return d * Math.PI / 180.0;    
    }   
    
         /**   
     * 通過經緯度獲取距離(單位:米)   
     * @param lat1   
     * @param lng1   
     * @param lat2   
     * @param lng2   
     * @return   
     */    
    public static double getDistance(double lat1, double lng1, double lat2,    
                                     double lng2) {    
        double radLat1 = rad(lat1);    
        double radLat2 = rad(lat2);    
        double a = radLat1 - radLat2;    
        double b = rad(lng1) - rad(lng2);    
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)    
                + Math.cos(radLat1) * Math.cos(radLat2)    
                * Math.pow(Math.sin(b / 2), 2)));    
        s = s * EARTH_RADIUS;    
        s = Math.round(s * 10000d) / 10000d;    
        s = s*1000;    
        return s;    
    } 
    
       
 
       /**
        * 新增索引,準備測試資料
        */
       public static void addIndex() {
              HttpSolrClient server = SolrServer.getServer();
              
              /**
               * 刪除舊索引
               */
              try {
                     server.deleteByQuery("*:*");
              } catch (SolrServerException e1) {
              } catch (IOException e1) {
                     e1.printStackTrace();
              }
              
              
              
              List<ProductBO> beans = new ArrayList<ProductBO>();
              // 家電類
              ProductBO dianshiBO1 = new ProductBO();
              dianshiBO1.setId("1001");
              dianshiBO1.setTitle("海爾模卡(MOOKA) 65K5 65英寸安卓智慧網路窄邊框全高清LED液晶電視");
              dianshiBO1.setMajor_s("家用電器");
              dianshiBO1.setSubMajor_s("電視");
              dianshiBO1.setBrand_s("海爾");
              dianshiBO1.setModel_s("65K5");
              dianshiBO1.setPrice_i(5400);
              dianshiBO1.setStation_address("廣東省廣州市海珠區新港東路1068號");
              //lat,lon
              dianshiBO1.setStation_position("23.104487,113.375981");
              
              beans.add(dianshiBO1);
              
              ProductBO dianshiBO2 = new ProductBO();
              dianshiBO2.setId("1002");
              dianshiBO2.setTitle("三星(SAMSUNG)UA55JU5900JXXZ 55英寸 4K超高清智慧 LED液晶電視 黑色");
              dianshiBO2.setMajor_s("家用電器");
              dianshiBO2.setSubMajor_s("電視");
              dianshiBO2.setBrand_s("三星");
              dianshiBO2.setModel_s("UA55JU5900");
              dianshiBO2.setPrice_i(6400);
              dianshiBO2.setStation_address("廣東省廣州市海珠區鳳浦中路741號");
              dianshiBO2.setStation_position("23.103373,113.374265");
              
              beans.add(dianshiBO2);
              
              dianshiBO2 = new ProductBO();
              dianshiBO2.setId("1002");
              dianshiBO2.setTitle("三星(SAMSUNG)UA55JU5900JXXZ 55英寸 4K超高清智慧 LED液晶電視 黑色");
              dianshiBO2.setMajor_s("家用電器");
              dianshiBO2.setSubMajor_s("電視");
              dianshiBO2.setBrand_s("三星");
              dianshiBO2.setModel_s("UA55JU5900");
              dianshiBO2.setPrice_i(6400);
              dianshiBO2.setStation_address("廣東省廣州市海珠區鳳浦中路741號");
              dianshiBO2.setStation_position("23.101811,113.376673");
              
              beans.add(dianshiBO2);
 
              ProductBO kongtiaoBO1 = new ProductBO();
              kongtiaoBO1.setId("2001");
              kongtiaoBO1.setTitle("格力(GREE) 大1匹 變頻 Q鉑 壁掛式冷暖空調 KFR-26GW/(26596)FNAa-A3");
              kongtiaoBO1.setMajor_s("家用電器");
              kongtiaoBO1.setSubMajor_s("空調");
              kongtiaoBO1.setBrand_s("格力");
              kongtiaoBO1.setModel_s("KFR-26GW/(26596)FNAa-A3");
              kongtiaoBO1.setPrice_i(7700);
              kongtiaoBO1.setStation_address("廣東省廣州市海珠區會展南五路");
              kongtiaoBO1.setStation_position("23.102359,113.377374");
              beans.add(kongtiaoBO1);
              
              ProductBO kongtiaoBO2 = new ProductBO();
              kongtiaoBO2.setId("2002");
              kongtiaoBO2.setTitle("奧克斯(AUX)正1.5匹 冷暖 定速 隱藏式顯示屏 壁掛式 空調 KFR-35GW/HFJ+3");
              kongtiaoBO2.setMajor_s("家用電器");
              kongtiaoBO2.setSubMajor_s("空調");
              kongtiaoBO2.setBrand_s("奧克斯");
              kongtiaoBO2.setModel_s("KFR-35GW/HFJ+3");
              kongtiaoBO2.setPrice_i(6600);
              kongtiaoBO2.setStation_address("廣東省廣州市海珠區新港東路1070號");
              kongtiaoBO2.setStation_position("23.103265,113.376718");
              beans.add(kongtiaoBO2);
              
              
              ProductBO kongtiaoBO3 = new ProductBO();
              kongtiaoBO3.setId("2003");
              kongtiaoBO3.setTitle("海爾(Haier)1.5匹 變頻 靜音空調 冷暖 壁掛式空調 KFR-35GW/01JDA23A");
              kongtiaoBO3.setMajor_s("家用電器");
              kongtiaoBO3.setSubMajor_s("空調");
              kongtiaoBO3.setBrand_s("海爾");
              kongtiaoBO3.setModel_s("KFR-35GW/01JDA23A");
              kongtiaoBO3.setPrice_i(9600);
              kongtiaoBO3.setStation_address("廣東省廣州市海珠區AAAAAAA");
              kongtiaoBO3.setStation_position("23.102667,113.376511");
              beans.add(kongtiaoBO3);
              
              
              ProductBO kongtiaoBO4 = new ProductBO();
              kongtiaoBO4.setId("2004");
              kongtiaoBO4.setTitle("廣東省廣州市天河區車陂,天園,棠下");
              kongtiaoBO4.setMajor_s("家用電器");
              kongtiaoBO4.setSubMajor_s("空調");
              kongtiaoBO4.setBrand_s("海爾");
              kongtiaoBO4.setModel_s("KFR-35GW/01JDA23A");
              kongtiaoBO4.setPrice_i(9600);
              kongtiaoBO4.setStation_address("廣東省廣州市天河區車陂,天園,棠下");
              kongtiaoBO4.setStation_position("23.125202,113.390858");
              beans.add(kongtiaoBO4);
 
              
              
              ProductBO kongtiaoBO5 = new ProductBO();
              kongtiaoBO5.setId("2005");
              kongtiaoBO5.setTitle("廣東省廣州市天河區科新路 棠下,天園,天河公園");
              kongtiaoBO5.setMajor_s("家用電器");
              kongtiaoBO5.setSubMajor_s("空調");
              kongtiaoBO5.setBrand_s("海爾");
              kongtiaoBO5.setModel_s("KFR-35GW/01JDA23A");
              kongtiaoBO5.setPrice_i(9600);
              kongtiaoBO5.setStation_address("廣東省廣州市天河區科新路 棠下,天園,天河公園");
              kongtiaoBO5.setStation_position("23.126299,113.387848");
              beans.add(kongtiaoBO5);
              
              ProductBO kongtiaoBO6 = new ProductBO();
              kongtiaoBO6.setId("2006");
              kongtiaoBO6.setTitle("廣東省廣州市海珠區閱江中路686");
              kongtiaoBO6.setMajor_s("家用電器");
              kongtiaoBO6.setSubMajor_s("空調");
              kongtiaoBO6.setBrand_s("海爾");
              kongtiaoBO6.setModel_s("KFR-35GW/01JDA23A");
              kongtiaoBO6.setPrice_i(9600);
              kongtiaoBO6.setStation_address("廣東省廣州市海珠區閱江中路686");
              kongtiaoBO6.setStation_position("23.10929,113.377472");
              beans.add(kongtiaoBO6);
              
           kongtiaoBO6 = new ProductBO();
              kongtiaoBO6.setId("2007");
              kongtiaoBO6.setTitle("廣東省廣州市海珠區鳳浦中路681號");
              kongtiaoBO6.setMajor_s("家用電器");
              kongtiaoBO6.setSubMajor_s("空調");
              kongtiaoBO6.setBrand_s("海爾");
              kongtiaoBO6.setModel_s("KFR-35GW/01JDA23A");
              kongtiaoBO6.setPrice_i(9600);
              kongtiaoBO6.setStation_address("廣東省廣州市海珠區鳳浦中路681號");
              kongtiaoBO6.setStation_position("23.101877,113.370349");
              beans.add(kongtiaoBO6);
              
           kongtiaoBO6 = new ProductBO();
              kongtiaoBO6.setId("2008");
              kongtiaoBO6.setTitle("廣東省廣州市海珠區會展南三路");
              kongtiaoBO6.setMajor_s("家用電器");
              kongtiaoBO6.setSubMajor_s("空調");
              kongtiaoBO6.setBrand_s("海爾");
              kongtiaoBO6.setModel_s("KFR-35GW/01JDA23A");
              kongtiaoBO6.setPrice_i(9600);
              kongtiaoBO6.setStation_address("廣東省廣州市海珠區會展南三路");
              kongtiaoBO6.setStation_position("23.10319,113.370088");
              beans.add(kongtiaoBO6);
              
              try {
                     server.addBeans(beans);
                     server.commit();
                     System.out.println("提交完畢!");
              } catch (Exception e) {
                     e.printStackTrace();
              }
       }
 
}
 
 
/**
 * 
 * @author Tony
 *
 */
public class SolrServer {
 
       private static SolrServer solrServer = null;
       private static HttpSolrClient server = null;
 
       private static String url = "http://localhost:8881/solr/test";
 
       public static synchronized SolrServer getInstance() {
              if (solrServer == null) {
                     solrServer = new SolrServer();
              }
              return solrServer;
       }
 
       public static HttpSolrClient getServer() {
              if (server == null) {
                     server = new HttpSolrClient.Builder(url).build();
                     server.setDefaultMaxConnectionsPerHost(1000);
                     server.setMaxTotalConnections(10000);
                     server.setConnectionTimeout(60000);// 設定連線超時時間(單位毫秒) 1000
                     server.setSoTimeout(60000);//// 設定讀資料超時時間(單位毫秒) 1000
                     server.setFollowRedirects(false);// 遵循從定向
                     server.setAllowCompression(true);// 允許壓縮
              }
              return server;
       }
}

這裡使用“經度 緯度”這樣的字串格式將經緯度索引到station_position欄位

3、查詢

查詢語法示例:

q={!geofilt pt=45.15,-93.85 sfield=poi_location_p d=5 score=distance}

q={!bbox pt=45.15,-93.85 sfield=poi_location_p d=5 score=distance}

q=poi_location_p:"Intersects(-74.093 41.042 -69.347 44.558)" //a bounding box (not in WKT)

q=poi_location_p:"Intersects(POLYGON((-10 30, -40 40, -10 -20, 40 20, 0 0, -10 30)))" //a WKT example

涉及到的欄位說明:

欄位

含義

q

查詢條件,如 q=poi_id:134567

fq

過濾條件,如 fq=store_name:農業

fl

返回欄位,如fl=poi_id,store_name

pt

座標點,如pt=54.729696,-98.525391

d

搜尋半徑,如 d=10表示10km範圍內

sfield

指定座標索引欄位,如sfield=geo

defType

指定查詢型別可以取 dismax和edismax,edismax支援boost函式相乘作用,dismax是通過累加方式計算最後的score.

qf

指定權重欄位:qf=store_name^10+poi_location_p^5

score

排序欄位根據qf定義的欄位defType定義的方式計算得到score排序輸出

其中有幾種常見的Solr支援的幾何操作:
WITHIN:在內部
CONTAINS:包含關係
DISJOINT:不相交
Intersects:相交(存在交集)

1)點查詢

測試程式碼:查詢距離某個點pt距離為d的集合

image.png

從這部分結果集中可以看出,資料是離目標點" 23.104487,113.375981 "最近的

多邊形查詢:

JtsSpatialContextFactory

  當有Polygon多邊形時會使用jts(需要把jts.jar放到solr webapp服務的lib下)。基本形狀使用SpatialContext (spatial4j的類)。

測試程式碼:

SolrQuery params = new SolrQuery();  

        //q=geo:"Intersects(POLYGON((-10 30, -40 40, -10 -20, 40 20, 0 0, -10 30)))"

        params.set("q", "station_position:\"Intersects(POLYGON((118 40, 118.5 40, 118.5 38, 118.3 35, 118 38,118 40)))\"");   

        params.set("start", "0");  //記錄開始位置

        params.set("rows", "100");  //查詢的行數

        params.set("fl", "*");

返回在這個POLYGON內的所有結果集。

管方文件:

 經緯度工具:

 百度地圖API工具:



檢視原文:http://www.dczou.com/viemall/793.html

相關推薦

基於Solr空間搜尋

概括:     最近一個專案需要基於LBS查詢附近的商鋪資訊,看了一下網上都是基於Solr和ELS方式來實現, 本來想使用ELS來實現的,但是由於專案以前用的是Solr, 所以就去調研了一下基於Solr來實現地理位置的搜尋,並且在實現的時候整理了一下實現的筆記。       

Solr針對空間搜尋的支援

Spatial Search Solr支援在地理空間搜尋中使用位置資料,使用空間搜尋,你可以: 索引點或者其他形狀 通過矩形框,圓或者其他形狀來過濾搜尋結果 通過點之間的距離 或者兩個區域之間的矩形之間的距離,排序或者增強分數 產生一個二維的網格來生成熱力

基於Solr的多表join查詢加速方法

bit 增量 一輪 send 阿裏雲 做了 activity 總結 周期 前言 DT時代對平臺或商家來說最有價值的就是數據了,在大數據時代數據呈現出數據量大,數據的維度多的特點,用戶會使用多維度隨意組合條件快速召回數據。數據處理業務場景需要實時性,需要能夠快速精準的獲得到需

基於狀態空間模型的PID控制器用M語言實現

公式 可能 不足 什麽是 摩擦 生活 pid bsp 時間 前面講到如何將狀態空間量建模,現在用PID控制方法並通過m語言來實現: 搞清楚這兩個問題,加深對PID控制器的理解: u = Kp * (x_last - x(i)) +   Ki * (x_last - 2 *

Lucene筆記11-Lucene的搜尋-基於QueryParser的搜尋

一、QueryParser查詢 QueryParser查詢功能是非常強大的,幾乎可以涵蓋前面所有的查詢,下面是方法體,它將query作為引數傳遞進來。 // 表示式查詢 public void searchByQueryParser(Query query, int number) {

基於solr實現商品資訊的全文檢索(windwons)

搭建環境 windows下tomcat+solr   相關軟體準備 1.安裝JDK 2.下載tomcat 3.下載solr-4.10.3.tgz.tgz 4.下載IK分詞器(IKAnalyzer2012FF_hf1.rar)   安裝步驟

Springboot+AngularJS+Spring-data-Solr搜尋內容匹配高亮顯示

Java後臺部分: package com.phubing.search.service.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframe

基於輕量級php搜尋sphider站內搜尋初級優化

轉載:https://blog.csdn.net/chijiaodaxie/article/details/48714373 站內搜尋初級優化 php1>. 概述: 站內搜尋引擎顧名思義即網站內的資訊搜尋引擎,隨著網路的發展,網站已經成為了企業或機構

使用solr完成搜尋功能

環境:linux系統 solr版本:solr-4.10.3.tar.gz 其他外掛: IK中文分詞器: IK Analyzer 2012FF_hf1 1、解壓solr-4.10.3.tar.gz 2、ll bin 3、在/usr/local下,mkdir solr 4、mv

vue基於elementUI整合搜尋與分頁的grid元件

檔案grid.vue為表格元件 index.vue為使用grid元件的demo result.json為結果的json檔案 在grid元件中想要回調父元件中的方法需要在grid元件中宣告: v-on:onDataBound="onDataBound" onDataBound=

自學大資料:Hive基於搜狗搜尋的使用者日誌行為分析

前言 ”大資料時代“,“大資料/雲端計算”,“大資料平臺”,每天聽到太多的大資料相關的詞語,好像現在說一句話不跟大資料沾邊都不好意思說自己是做IT的。可能這與整個IT圈子的炒作也有關聯,某一個方面來看其實就是一營銷術語。很多朋友就想問,我想做大資料,但是沒有這個條件,沒有這

如何在thinkPHP5中使用mongoDB中空間搜尋進行位置範圍查詢

在很多場景我們都會使用位置範圍服務,如查詢附近的單車、紅包數量等。網上已有很多關於mongoDB空間搜尋的文章,由於thinkPHP的使用人還是比較多的,但還沒有關於thinkPHP5中如何使用的相關文章。thinkPHP5中的查詢條件已經預設擁有了near查詢處理,但結果

Solr全文搜尋伺服器

                                 Solr全文搜尋伺服器   示意圖&nb

狀態空間搜尋——八數碼問題 Java實現

狀態空間搜尋——八數碼問題  實驗報告 【注】原始碼將以附件的形式上傳,其中EightPuzzle.java為vo類,EightPuzzleOperator.java為util類,EightPuzzleAlgorithm.java為演算法實現類。Main函式在Eight

8_ElaticSearch 基於boost的搜尋條件權重控制

8_ ElaticSearch 基於boost的搜尋條件權重控制更多幹貨需求搜尋標題中包含java的帖子同時,如果標題中包含hadoop或elasticsearch就優先搜尋出來同時,如果一個帖子包含j

基於空間的熱備(推薦使用這種方式)

set feedback off set heading off set verify off set trimspool off set pagesize 0 set linesize 200 define dir = '/home/oracle/hotbak' define script = '

基於jquery的搜尋框輸入提示

 仿百度與google的搜尋框輸入提示,支援鍵盤上下選擇與滑鼠點選選擇。只包含前面程式碼,後臺返回資料為模擬的資料。 1.未輸入前的效果 2.輸入內容後,自動彈出下拉層,裡面有若干匹配輸入內容的輸入建議項 3.按下鍵盤的↑↓鍵可以在下面的輸入提示項中進行選擇,選中的項自

海量搜尋服務架構搭建1-基於spring的搜尋服務

相當於一個百度搜索系統 幾個名詞解釋 Lucene簡介 1.什麼是lucene? Lucene是一個全文搜尋框架,而不是應用產品。因此它並不像http://www.baidu.com/ 或者google Desktop那麼拿來就能用,它只是提供

基於Elasticsearch實現搜尋建議

搜尋建議是搜尋的一個重要組成部分,一個搜尋建議的實現通常需要考慮建議詞的來源、匹配、排序、聚合、關聯的文件數和拼寫糾錯等,本文介紹一個基於Elasticsearch實現的搜尋建議。 問題描述 電商網站的搜尋是最基礎最重要的功能之一,搜尋框上面的良好體驗能

連通域標記演算法(二) 基於深度優先搜尋的連通域標記演算法(opencv C++實現)

        上一篇我們講到了MATLAB中的bwlabel連通域標記演算法的C++實現https://blog.csdn.net/Dhane/article/details/81633723,今天我來講一講另一種相對比較容易想到的連通域標記演算法。簡單點說