Neo4j Spatial使用指南(一)
译者声明
你好!
本中文版Neo4j Spatial使用指南仅供学习交流使用而翻译,转载请注明出处,所有权利归原作者。
译者才疏学浅,还在学习中,欢迎捉虫指正和讨论!
这篇中文指南基于
Neo4j Spatial v0.24-neo4j-3.1.4
文档翻译。
引言 Introduction
Neo4j Spatial是Neo4j的实用程序库,它可以便利地对数据进行空间操作,尤其是对已定位数据添加空间索引,并对数据执行空间操作。比如说,您可以在指定区域内或兴趣点指定距离内搜索数据。
此外,Neo4j Spatial还提供了一些类,这些类可以将数据传送到GeoTools。借此,GeoTools可以将数据提供给支持GeoTools的应用程序使用,如GeoServer和uDig。
Neo4j Spatial的主要功能包括:
- 导入数据的实用程序(Utilities):能导入ESRI Shapefile以及Open Street Map文件数据;
- 支持所有常见的几何类型:点(Point),线串(LineString),多边形(Polygon)等;
- RTree索引,可快速搜索几何图形;
- 支持搜索过程中的拓扑操作(包含contains,内部within,相交intersects,覆盖covers,不相交disjoint等)
- 无论怎样存储空间数据,只要能为地图提供从图谱(graph)到几何图形(geometries)的提供适配器,Neo4j Spatial就可以在任何数据图上启用空间操作;
- Neo4j Spatial能够使用预先配置的过滤器,将单个层或数据集拆分为多个子层(sub-layers)或视图(views)。
开始使用 Get Started
开始使用neo4j-spatial的最简单方法是从
最新版本
中获取server-plugin-*。jar,将其复制到$ NEO4J_HOME / plugins并重新启动Neo4j服务器。
在那里,您可以在Cypher查询中使用所有Neo4j Spatia过程(Neo4j Spatial Procedures,见第四节)将结点(Node)添加到空间索引中,并执行许多空间点,距离和交叉点查询操作。
Simple Example
//Simple Example
CALL spatial.addPointLayer('geom');
CALL spatial.layers();
CREATE (n:Node {latitude:60.1,longitude:15.2})
WITH n
CALL spatial.addNode('geom',n) YIELD node
RETURN node;
CALL spatial.bbox('geom',{lon:15.0,lat:60.0}, {lon:15.3, lat:61.0});
接下来是三篇示例文章。
一篇很好的示例博客文章:关于如何用一种neo4j驱动程序使用这些过程,由
William Lyon
在
(Part 1)
撰写的
Spatial Procedures in Legis Graph
。
Max de Marzi
在他的
两篇关于餐厅推荐的博客文章
中解释了
如何使用Neo4j Spatial Server插件
。
Craig Taverner
在
博客文章
中对Neo4j Spatial进行了简单介绍,并做了有关如何使用Spatial Java API的简单示例。
索引和查询 Index and Querying
Neo4j Spatial当前使用的索引是RTree,但它已经以可扩展的方式开发过,如有必要,允许添加其他索引。
加载和索引 Loading and Indexing
在加载过程中,可以将数据导入到数据库中,然后将其添加到索引中。稍后也可以将现有空间数据添加到索引。这是两种截然不同的场景,实际上会产生不同的图结构,我们将依次对这两种情况进行解释。
要将数据直接加载到索引中,最简单的方法是从创建适合您数据的图层(Layer)开始。 Neo4j-Spatial内置了许多可能的选项,而两个常见的选项是:
- SimplePointLayer – 一个可编辑的层,仅允许您将点添加到数据库。如果您只有点数据并且主要对邻近搜索感兴趣,那么这是一个不错的选择。该层包括专门针对该情况的实用程序方法。
- EditableLayer(Impl)- 这是默认的可编辑图层实现接口(the default editable layer implementation),可以处理任何类型的简单几何。简单几何包括Point,LineString和Polygon,以及Multi-Point,Multi-LineString和Multi-Polygon。由于它是通用实现接口,并且无法了解数据模型的拓扑,因此它将每个几何图形分别存储在单个节点的单个属性中。存储格式为WKB(Well Known Binary),这是一种针对地理几何的二进制格式。流行的开源空间数据库PostGIS也使用这种格式。
图层和几何编码器 Layers and GeometryEncoders
定义几何集合的主要类型是图层。图层包含用于查询的索引。此外,如果可以在图层中添加和修改几何图形,则该图层可以是可编辑图层,即EditableLayer。
下一个最重要的接口是几何编码器,即GeometryEncoder。
DefaultLayer是标准层,利用WKBGeometryEncoder将所有几何类型存储为每个几何实例一个节点的byte []属性。
OSMLayer是一种特殊层,可以支持Open Street Map并将OSM模型存储为单个完全连接的图形。该层提供的几何集包括Points, LineStrings和Polygons,从而不能导出为Shapefile格式,因为该格式仅允许每层一个几何。但是,OMSLayer继承了DynamicLayer,这使得OMSLayer可以提供任意数量的子层,每个子层都基于一个OSM标签过滤器(OSM tag filter),具有特定的几何类型。例如,您可以创建一个以LineStrings形式绘制所有自行车道的层,或一个以Polygons形式绘制所有湖泊的层。在它们的下方,它们仍然由相同的完全连接的图支持,但是作为明显独立的几何层动态展示。
Neo4j Spatial过程 Neo4j Spatial Procedures
Neo4j Spatial也被打包成了ZIP文件,可以解压缩到Neo4j服务器的$NEO4J_HOME/plugins目录中。重新启动服务器后,您应该能够使用以下来自Cypher查询语言的过程调用。
Table 1. Available Spatial Procedures
name | description | signature |
---|---|---|
“spatial.addLayer” | “Adds a new layer with the given type (see spatial.getAllLayerTypes) and configuration, returns the layer root node” | “spatial.addLayer(name :: STRING?, type :: STRING?, encoderConfig :: STRING?) :: (node :: NODE?)” |
“spatial.addLayerWithEncoder” | “Adds a new layer with the given encoder class and configuration, returns the layer root node” | “spatial.addLayerWithEncoder(name :: STRING?, encoder :: STRING?, encoderConfig :: STRING?) :: (node :: NODE?)” |
“spatial.addNode” | “Adds the given node to the layer, returns the geometry-node” | “spatial.addNode(layerName :: STRING?, node :: NODE?) :: (node :: NODE?)” |
“spatial.addNodes” | “Adds the given nodes list to the layer, returns the count” | “spatial.addNodes(layerName :: STRING?, nodes :: LIST? OF NODE?) :: (count :: INTEGER?)” |
“spatial.addPointLayer” | “Adds a new simple point layer, returns the layer root node” | “spatial.addPointLayer(name :: STRING?) :: (node :: NODE?)” |
“spatial.addPointLayerWithConfig” | “Adds a new simple point layer with the given configuration, returns the layer root node” | “spatial.addPointLayerWithConfig(name :: STRING?, encoderConfig :: STRING?) :: (node :: NODE?)” |
“spatial.addPointLayerXY” | “Adds a new simple point layer with the given properties for x and y coordinates, returns the layer root node” | “spatial.addPointLayerXY(name :: STRING?, xProperty :: STRING?, yProperty :: STRING?) :: (node :: NODE?)” |
“spatial.addWKT” | “Adds the given WKT string to the layer, returns the created geometry node” | “spatial.addWKT(layerName :: STRING?, geometry :: STRING?) :: (node :: NODE?)” |
“spatial.addWKTLayer” | “Adds a new WKT layer with the given node property to hold the WKT string, returns the layer root node” | “spatial.addWKTLayer(name :: STRING?, nodePropertyName :: STRING?) :: (node :: NODE?)” |
“spatial.addWKTs” | “Adds the given WKT string list to the layer, returns the created geometry nodes” | “spatial.addWKTs(layerName :: STRING?, geometry :: LIST? OF STRING?) :: (node :: NODE?)” |
“spatial.asExternalGeometry” | “Returns a geometry object as an external geometry type to be returned to a client” | “spatial.asExternalGeometry(geometry :: ANY?) :: (geometry :: ANY?)” |
“spatial.asGeometry” | “Returns a geometry object as an internal cypher geometry type, to be passed to other procedures but not returned to a client” | “spatial.asGeometry(geometry :: ANY?) :: (geometry :: ANY?)” |
“spatial.bbox” | “Finds all geometry nodes in the given layer within the lower left and upper right coordinates of a box” | “spatial.bbox(layerName :: STRING?, min :: ANY?, max :: ANY?) :: (node :: NODE?)” |
“spatial.closest” | “Finds all geometry nodes in the layer within the distance to the given coordinate” | “spatial.closest(layerName :: STRING?, coordinate :: ANY?, distanceInKm :: FLOAT?) :: (node :: NODE?)” |
“spatial.decodeGeometry” | “Returns a geometry of a layer node as internal cypher geometry type, to be passed to other procedures but not returned to a client” | “spatial.decodeGeometry(layerName :: STRING?, node :: NODE?) :: (geometry :: ANY?)” |
“spatial.getFeatureAttributes” | “Returns feature attributes of the given layer” | “spatial.getFeatureAttributes(name :: STRING?) :: (name :: STRING?)” |
“spatial.importOSM” | “Imports the the provided osm-file from URI to a layer of the same name, returns the count of data added” | “spatial.importOSM(uri :: STRING?) :: (count :: INTEGER?)” |
“spatial.importOSMToLayer” | “Imports the the provided osm-file from URI to a layer, returns the count of data added” | “spatial.importOSMToLayer(layerName :: STRING?, uri :: STRING?) :: (count :: INTEGER?)” |
“spatial.importShapefile” | “Imports the the provided shape-file from URI to a layer of the same name, returns the count of data added” | “spatial.importShapefile(uri :: STRING?) :: (count :: INTEGER?)” |
“spatial.importShapefileToLayer” | “Imports the the provided shape-file from URI to the given layer, returns the count of data added” | “spatial.importShapefileToLayer(layerName :: STRING?, uri :: STRING?) :: (count :: INTEGER?)” |
“spatial.intersects” | “Returns all geometry nodes that intersect the given geometry (shape, polygon) in the layer” | “spatial.intersects(layerName :: STRING?, geometry :: ANY?) :: (node :: NODE?)” |
“spatial.layer” | “Returns the layer root node for the given layer name” | “spatial.layer(name :: STRING?) :: (node :: NODE?)” |
“spatial.layerTypes” | “Returns the different registered layer types” | “spatial.layerTypes() :: (name :: STRING?, signature :: STRING?)” |
“spatial.layers” | “Returns name, and details for all layers” | “spatial.layers() :: (name :: STRING?, signature :: STRING?)” |
“spatial.procedures” | “Lists all spatial procedures with name and signature” | “spatial.procedures() :: (name :: STRING?, signature :: STRING?)” |
“spatial.removeLayer” | “Removes the given layer” | “spatial.removeLayer(name :: STRING?) :: VOID” |
“spatial.setFeatureAttributes” | “Sets the feature attributes of the given layer” | “spatial.setFeatureAttributes(name :: STRING?, attributeNames :: LIST? OF STRING?) :: (node :: NODE?)” |
“spatial.updateFromWKT” | “Internal procedure, updates the geometry node with the given id with a new WKT string” | “spatial.updateFromWKT(layerName :: STRING?, geometry :: STRING?, geometryNodeId :: INTEGER?) :: (node :: NODE?)” |
“spatial.withinDistance” | “Returns all geometry nodes and their ordered distance in the layer within the distance to the given coordinate” | “spatial.withinDistance(layerName :: STRING?, coordinate :: ANY?, distanceInKm :: FLOAT?) :: (node :: NODE?, distance :: FLOAT?)” |