空间索引的空间索引类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了空间索引的空间索引类型相关的知识,希望对你有一定的参考价值。

参考技术A

R树
R树是B树向多维空间发展的另一种形式,它将空间对象按范围划分,每个结点都对应一个区域和一个磁盘页,非叶结点的磁盘页中 存储其所有子结点的区域范围,非叶结点的所有子结点的区域都落在它的区域范围之内;叶结点的磁盘页中存储其区域范围之内的所有空间对象的外接矩形。每个结点所能拥有的子结点数目有上、下限,下限保证对磁盘空间的有效利用,上限保证每个结点对应一个磁盘页,当 插入新的结点导致某结点要求的空间大于一个磁盘页时,该结点一分为二。R树 是一种动态索引结构,即:它的查询可与插入或删除同时进行,而且不需要定期地对树结构进行重新组织。
1 R-Tree数据结构
R-Tree是一种空间索引数据结构,下面做简要介绍:
(1)R-Tree是n 叉树,n称为R-Tree的扇 (fan)。
(2)每个结点对应一个矩形。
(3)叶子结点上包含 了小于等于n 的对象,其对应的矩为所有对象的 外包矩形。
(4)非叶结点的矩形为所有子结点矩形的外包矩形。
R-Tree的定义很宽泛,同一套数据构造R-Tree,不同方可以得到 差别很大的结构。什么样的结构比较优呢?有两标准:
(1)位置上相邻的结点尽量在树中聚集为一个父结点。
(2)同一层中各兄弟结点相交部分比例尽量小。
R树是一种用于处理多维 数据的数据结构,用来访问二维或者更高维区域对象组成的空间数据.R树是一棵平衡树。树上有两类结点:叶子结点和非叶子结点。每一个结点由若干个索引项构成。对于叶子结点,索引项形如(Index,Obj_ID)。其中,Index表示包围空间数据对象的最小外接矩形MBR,Obj_ID标识一个空间数据对象。对于一个非叶子结点,它的 索引项形如(Index,Child_Pointer)。 Child_Pointer 指向该结点的子结点。Index仍指一个矩形区域,该矩形区 域包围了子结点上所有索引项MBR的最小矩形区域。一棵R树的示例如图所示:
2 R-Tree算法描述
算法描述如下:
对象数为n,扇区大小定为fan。
(1)估计叶结点数k=n/fan。
(2)将所有几何对象按照其矩形外框中心点的 x值排序。
(3)将排序后的对象分组,每组大小为 *fan,最后一组可能不满员。
(4)上述每一分组内按照几何对象矩形外框中心点的y值排序。
(5)排序后每一分组内再分组,每组大小为fan。
(6)每一小组成 为叶结点,叶子结点数为nn。
(7)N=nn,返回1。
3 R-Tree空间索引算法的研究历程
1 R-Tree
多维索引技术的历史可以追溯到20世纪70年代中期。就在那个时候,诸如Cell算法、四叉树和k-d树等各种索引技术纷纷问世,但它们的效果都不 尽人意。
R+树
在Guttman的工作的基础上,许多R树的变种被开发出来, Sellis等提出了R+树,R+树与R树类似,主要区别在于R+树中兄弟结点对应的空间区域无重叠,这样划分空间消除了R树 因允许结点间的重叠而产生的“死区域”(一个结点内不含本结点数据的空白区域),减少了无效查询数,从而大大提高空间索引的效率,但对于插入、删除空间对象的操作,则 由于操作要保证空间区域无重叠而效率降低。同时R+树对跨区域的空间物体的数据的存储是有冗余的,而且随着数据库中数据的增多,冗余信息会不断增长。Greene也提出了他的R树的变种。
R*树
在1990年,Beckman和Kriegel提出了最佳动态R树的变种——R*树。R*树和R树一样允许矩形的重叠,但在构造算法R*树不仅考虑了 索引空间的“面积”,而且还考虑了索引空间的重叠。该方法对结点的插入 、分裂算法进行了改进,并采用“强制重新插入”的方法使树的结构得到优化。但 R*树算法仍然不能有效地降低空间的重叠程度,尤其是在数据量较大、空间维数增加时表现的更为明显。R*树无法处理维数高于20的情况。
QR树
QR树利用四叉树将空间划分成一些子空间,在各子空间内使用许多R树索引,从而改良索引空间的重叠。QR树结合了四叉树与R树的优势,是二者的综合应用。实验证明:与R树相比,QR树以略大(有时甚至略小)的空间开销代价,换取了更高的性能,且索引目标数 越多,QR树的整体性能越好。
SS树
SS树对R*树进行了改进,通过以下措施提高了最邻近查询的性能:用最小边界 圆代替最小边界矩形表示区域的形状,增强了最邻近查询的性能,减少将近一半 存储空间;SS树改进了R*树的强制重插机制。当维数增加到5是,R树及其变种中的边界矩形的重叠将达到90%,因此在高维情况(≥5)下,其性能将变的很差,甚至不如顺序扫描。
X树
X树是线性数组和层状的R树的杂合体,通过引入超级结点,大大地减少了最小边界矩形之间的重叠,提高了查询效率。X树用边界圆进行索引, 边界矩形的直径(对角线)比边界圆大,SS树将点分到小直径区域。由于区域的直径对最邻近查询性能的影响较大 ,因此SS树的最邻近查询性能优于R*树 ;边界矩形的平均容积比边界圆小,R*树将点分到小容积区域;由于大的容积会产生较多的覆盖,因此边界矩形在容积方面要优于边界圆。SR树既采用了最小边界圆(MBS ),也采用了最小边界矩形(MBR),相对于SS树,减小了区域的面积,提高了区域之间的分离性,相对于R*树,提高了邻近查询的性能。

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 )是否为同一个图形

关于空间类型的WKT表示方法,详细请看如下地址:https://en.wikipedia.org/wiki/Well-known_text

/**
	 * @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对多边形(点、线、多边形)数据的索引与搜索,同时还提供了空间搜索中相关的过滤器,希望大家共同学习,如果有什么不正确的地方,还望大家指出。

以上是关于空间索引的空间索引类型的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB——索引类型之地理空间索引(Geospatial Index)

Solr的空间索引

Solr的空间索引

postgis sql查询空间索引失效

聊聊MySQL几大索引类型:B-Tree索引,哈希索引,R-Tree空间数据索引,全文索引

高效空间数据索引R树及其批量加载方法STR简介