1. 程式人生 > >Solr的空間索引

Solr的空間索引

一、Solr空間搜尋的目的

(1)索引空間點資料和其他形狀的資料

(2)通過圓形、正方形或者其他形狀進行過濾搜尋結果

(3)通過兩個點之間的距離或者是兩個多邊形的形狀進行排序或者評分

二、Solr空間搜尋的域型別(FieldType)

1 、LatLonType與POINT

這兩種型別都是資料點型別。LatLonType型別儲存一個點在地圖上的經緯度資訊。POINT型別則是儲存一個點在座標上的x y位置。點型別資料的表達方式為lat(x),lon(y)。

2、SpatialRecursivePrefixTreeFieldType型別(縮寫為RPT型別)

A、RPT除了能夠在圓形和正方形外,還能在多邊形和其他複雜的形狀進行搜尋

B、對點和多邊形(線、多邊形)進行索引建立。

C、多值的距離上的排序和評分boost

RPT域型別使用時,需要在模式檔案中進行建立:

(1)下載JTS

JTS的下載地址:http://download.csdn.net/detail/u011518678/9613072

將JTS下載後,直接將jts的jar放入到solr web工程下的lib資料夾即可。

(2)配置RPT域型別,建立多邊形域

<fieldType name="shape_rpt" class="solr.SpatialRecursivePrefixTreeFieldType" 
    spatialContextFactory="com.spatial4j.core.context.jts.JtsSpatialContextFactory" distErrPct="0.025" maxDistErr="0.000009" units="degrees"></fieldType>
<field name="shape" type="shape_rpt" indexed="true" stored="true"></field>

field的定義不在過多描述,下面主要介紹RPT域型別相關的屬性:

name:域型別的名稱

class:該型別的資料有那個類進行處理,這裡使用solr.SpatialRecursivePrefixTreeFieldType

spatialContextFactory:solr本身只支援點和矩形的形狀處理,需要通過JTS工具來擴充套件多邊形的功能。如果需要的話則需要擴充套件JTS jar中的JtsSapatialContextFactory物件。需要注意的是,solr5.x和solr6.x版本中的ContexntFacotory的package路徑是不一樣的,solr5:com.spatial4j.core.context.jts.JtsSpatialContextFactory,solr6:org.locationtech.spatial4j.context.jts.JtsSpati

,所以使用者在配置RPT域型別時要根據自己的solr版本配置不同的包路徑。

maxDistErr:定義索引資料的最高界別,預設是地面1米(0.000009度)。

unutis:索引的資料所使用的單位,可以定義為degrees,kilometers和miles,預設值為kilometers

distErrPct:0-0.5之間的範圍,定義了距離的經度,當值越消失,則精度越高。

(3)操作多邊形資料

建立索引:

在建立索引時,需要注意多邊形在索引資料中的表達方式:

點的表達方式為:POINT(0 0)

線的表達方式為:LINESTRING(0 0,1 0,0 0),線段由多個點組成,線段當含有多個點時,則是折線

多邊形的表達方式:POLYGON(0 0,1 0,1 1,1 0,0 0 ),多邊形的表達方式需要形成閉合圖形,但是筆者沒有證明POLYGON(0 0,1 0,1 1,1 0,0 0 )是否和POLYGON(0 0,1 1,0 1,1 0,0 0 )是否為同一個圖形

/**
	 * @author wozipa
	 * @throws IOException 
	 * @throws SolrServerException 
	 * @Date 2016-8-24 9:53
	 * @see 所以多邊形檔案
	 * POLYGON((0 0,0 1,1 1,1 0,0 0))
	 * POIN(0 0)
	 * LINESTRING(0 0,1 0,0 0)
	 */
	public void indexPolygon() throws SolrServerException, IOException
	{
		HttpSolrClient client=new HttpSolrClient("http://192.98.12.36:8983/solr/Test");
		SolrInputDocument document=new SolrInputDocument();
		document.addField("id", "test4");
		document.addField("shape", "POIN(0 0)");  //空間點表示方法:POIN(0 0)
		document.addField("shape", "LINESTRING(0 0,1 0,0 0)"); //空間線表示方法:LINESTRING(0 0,1 0,0 0),三個點,形成閉合圖形
		document.addField("shape", "POLYGON((0 0,0 1,1 1,1 0,0 0))");  //空間多邊形表示方法:POLYGON((0 0,0 1,1 1,1 0,0 0)),這裡表示一個四邊形
																	   //五個點,形成閉合圖形
		client.add(document);
		client.commit();
	}

索引的結果為:

 {
        "id": "test4",
        "shape": "LINESTRING(0 0,1 0,0 0)",
        "_version_": 1543642553156370400
  }

建立查詢:

多邊形的查詢則為兩個多邊形的關係,主要包括:相交(Intersects),包含(Contains),被包含(Within),相等(Equals)和相拒(Disjoint),查詢的基本公式為:

"action+polygon":例如

"Intersects(POLYGON(0 0,1 0,1 1,0 1,0 0))"
空間索引資料查詢的程式碼為:
/**
	 * @author wozipa
	 * @Date 2016-8-24 10:12
	 * @see 對該多邊形就行查詢
	 */
	public void queryPolygon()
	{
		HttpSolrClient client=new HttpSolrClient("http://192.98.12.36:8983/solr/Test");
		SolrQuery query=new SolrQuery();
		query.setQuery("shape:\"Intersects(POLYGON((0 0,0 0.5,0.5 0.5,0.5 0,0 0)))\"");
		try {
			SolrResponse response=client.query(query);
			System.out.println(response.toString());
		} catch (SolrServerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * @author wozipa
	 * @Date 2016-8-24 11:08
	 * @see 查詢點
	 */
	public void queryPoint()
	{
		HttpSolrClient client=new HttpSolrClient("http://192.98.12.36:8983/solr/Test");
		SolrQuery query=new SolrQuery();
		query.setQuery("shape:\"Intersects(POINT(2.1 2.1))\"");
		try {
			SolrResponse response=client.query(query);
			System.out.println(response.toString());
		} catch (SolrServerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

3、BBoxField

該型別是solr6版本中新增加的,是一個RPT型別的一個變種(我認為是簡化版本),對舉行表示式發生了改變:ENVELOPE(minX,maxX,maxY,minY)

ENVELOPE(-10, 20, 15, 10)

該型別的使用方式基本和POLYGON是相同的,主要為資料的定義:

<field name="bbox" type="bbox" />
<fieldType name="bbox" class="solr.BBoxField"
        geo="true" units="kilometers" numberType="_bbox_coord" storeSubFields="false"/>
<fieldType name="_bbox_coord" class="solr.TrieDoubleField" precisionStep="8" docValues="true" stored="false"/>

筆者沒有對該型別進行研究,就是簡單的提示一下solr使用者,在solr6中新增加了一種矩形的表達方式。

三、過濾器

在空間搜尋中,solr還提供了兩種常用的filter,用來對結果集進行過濾篩選,過濾器擁有共同的引數型別,下面先介紹一下各個引數型別

1、引數

(1)d

兩個多邊形之間的線性距離,預設使用單位為千米(1km=0.009度),可以d進行單位定義

(2)pt

中心點位置,使用x,y進行點的表示。

(3)sfield

進行空間過濾的域名城,即該名稱的空間資料將被用於資料過濾

(4)filter

過濾器名城,主要有兩種型別,geofilter和bbox

通過這四個引數可以確定一個範圍,該範圍外的資料將被過濾掉。

2、過濾器型別

(1)geofilt

該型別將生成一個以pt為中點,以d為半徑,形成一個圓形,該圓形中的資料符合過濾器的條件,不會被過濾掉。

使用例子為:fq={!geofilt sfield=store}&pt=45.15,-93.85&d=5,可以將所有的條件資料寫入到大括號內:fq={!geofilt sfield=storept=4515,-93.85 d=5}

(2)bbox

該過濾器,會先畫一個域geofilt相同的圓,然後形成一個與圓外切的正方形,該正方形中的資料通過過濾器,起範圍表示為下圖中的藍色方框:

使用方式為:fq={!bbox sfield=store}&pt=45.15,-93.85&d=5,其用法如上:

四、總結

該問主要講解了solr對多邊形(點、線、多邊形)資料的索引與搜尋,同時還提供了空間搜尋中相關的過濾器,希望大家共同學習,如果有什麼不正確的地方,還望大家指出。