1.Neo4j Spatial 簡介
1.1Neo4j Spatial概念
Neo4j Spatial項目是圖數據庫Neo4j的一個插件,它通過將空間數據映射到圖模型(graph model),它將對象和關系當作頂點和邊存儲在圖模型中。因而使得Neo4j具有空間數據的導入,存儲,查詢等功能[8]。Neo4j Spatial支持的地理要素遵循OpenGIS的規范[9],包括點(point),線段(line-string),面(polygon),多點(multipoint),多線段(multi-linestring)等簡單要素。Neo4j Spatial使用R樹作為空間索引,主要是集成了Lucene 的索引庫,支持的空間查詢包括覆蓋(cover),被覆蓋(cover by),包含(contian),相交(intersect)等。一般而言,R樹會將葉子結點(COUNT,LEVEL,<OIi,MBRi>)上幾何要素分組並用它們的數據矩形來表示,相比PostGIS所使用的優化過GisT[13]索引要低效,會使Neo4j在范圍查詢上效率有所不及PostGIS,但它對適合圖模型的數據(如網絡數據)操作效率非常高[14]。綜上所述,Neo4j在符合圖數據模型的分析中如鄰近搜索,路徑分析等這些特定類型的應用有非常大的優勢。
Neo4J圖數據庫實踐系列
圖數據庫實踐系列 (一)--Neo4J簡介與安裝 http://www.linuxidc.com/Linux/2013-08/88766.htm
圖數據庫實踐系列 (二)--Neo4J空間數據存儲 http://www.linuxidc.com/Linux/2013-08/88767.htm
圖數據庫實踐系列 (三)--Neo4j Spatial的REST集成 http://www.linuxidc.com/Linux/2013-08/88768.htm
1.2 Neo4j Spatial特性
Neo4j Spatial的部分核心特性包括
- 支持Esri Shapefile格式,OSM(OpenStreetMap)格式(只支持.osm格式)(補充:Open Street Map目前逐步適用PBF替代OSM)
- 支持所有通用的幾何要素
- 在空間查詢的時候支持拓撲操作
- 允許任何圖數據都實現空間操作功能
- 能夠將單一圖層或者數據集拆分成多個子圖層
2.Neo4j Spatial安裝
2.1 EGit安裝
EGit是Eclipse團隊提供的Git插件,它基於JGit(Git的java實現版本)實現的,允許在Eclipse中實現Git的各種命令[15]。它的安裝和其他插件一樣,在eclipse中選擇Help->Install New Software,加入Update site http://download.eclipse.org/egit/updates 會如圖1所示:
圖1 安裝EGit
安裝成功的話,需要重啟Eclipse。File ->New -> Other,會看到Git的字樣。
2.2 M2eclipse安裝
M2eclipse是Maven的Eclipse插件,項目的目標是提供為Eclipse 提供一流的Maven支持,使它能夠更方便地編輯POM文件,構建項目等[16]。同樣可以通過Update Site 安裝:http://download.eclipse.org/technology/m2e/releases。如圖2所示:
圖2 安裝M2Eclipse
安裝成功的話,需要重啟Eclipse。File ->New -> Other,會看到Maven的字樣。
2.2Neo4j Spatial安裝
Neo4j Spatial源碼可以在Github下載,我們通過以上安裝的兩個插件,來構建和安裝我們的Neo4j Spatial項目。首先在eclipse中File中導入Git項目,
File -> Import -> Git -> Project from Git.如果本地已經存在Git庫,可以選擇Local.我們遠程下載Spatial,選擇URI,如圖3所示。
圖3 選擇遠程庫
輸入Neo4j Spatial URI,然后Next,如圖-4所示:
圖4 輸入URI
EGit會自動Fetch回所有的源碼,我們可以按照自己需要選擇特定版本,然后Next。如圖5所示:
圖5 選擇源碼版本
然后可以一直Next,直至選擇導入的項目類型,選擇Import as general projcet.如圖6 所示:
圖6 導入項目
再Next然后點finish 完成neo4j spatial 的導出。此時,還需要將該項目轉化成Maven Project ,選中項目,右鍵:Configure ->Convert to Maven Project.最后我們得到了一個git管理下的maven項目。使用如下命令來安裝Neo4j Spatial。
mvn clean install
在eclipse操作是 Run as ->5. Maven Build ->輸入構建目標。 如圖7所示:
圖7 構建Neo4j Spatial 項目
M2eclipse會自動構建工程。如果安裝失敗的話,可以使用如下命令跳過單元測試
mvn clean install -DskipTests
最后eclipse的console會報出build success。
3.Neo4j Spatial 空間數據讀取
3.1地理圖層與編碼
Spatial 庫中首先需要定義圖層中幾何要素,可供查詢的索引,同時圖層是否可編輯 ,其次是確定幾何編碼接口。Spatial類庫提供的默認圖層是標准圖層,使用WKBGeometryEncoder,將所有的要素以字節數組的形式來存 儲。地理數據中實體的屬性會當作圖數據模型中頂點的屬性來存儲。OSMLayer 是支持Open Street Map格式的特殊圖層,neo4j使用單個完全圖[17]來存儲該圖層。同時 OMSLayer繼承動態圖層,允許包含任意個子圖層。
3.2導入shapefile
導入shapefile大概過程是1.生存Neo4j數據庫(調用已有) 2.實例化,並調用ShapefileImporter 3.關閉數據庫 實例代碼如下所示:

package edu.sirc.gis.data;import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.Charset;
import org.geotools.data.shapefile.shp.ShapefileException; import org.neo4j.gis.spatial.Layer; import org.neo4j.gis.spatial.ShapefileImporter; import org.neo4j.gis.spatial.SpatialDatabaseService; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.kernel.EmbeddedGraphDatabase;
public class importShapefiletest {
/** * @param args * import shapefile to neo4j database * just Extract from the org.neo4j.gis.spatial.testfordoc */ private String databasepath="/home/vent/environment/neo4j/gis";
public void importShapfile() throws ShapefileException, FileNotFoundException, IOException
{
System.out.println("\n=== Test Import Shapefile ===");</span><span class="typ">GraphDatabaseService</span><span class="pln"> graphdb </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">EmbeddedGraphDatabase</span><span class="pun">(</span><span class="pln">databasepath</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">ShapefileImporter</span><span class="pln"> shpImporter </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ShapefileImporter</span><span class="pun">(</span><span class="pln">graphdb</span><span class="pun">);</span><span class="pln"> shpImporter</span><span class="pun">.</span><span class="pln">importFile</span><span class="pun">(</span><span class="str">"/home/vent/environment/neo4j/data/shp/river.shp"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"river"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Charset</span><span class="pun">.</span><span class="pln">forName</span><span class="pun">(</span><span class="str">"UTF-8"</span><span class="pun">));</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">finally</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> graphdb</span><span class="pun">.</span><span class="pln">shutdown</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
}
public static void main(String[] args) throws ShapefileException, FileNotFoundException, IOException {
// TODO Auto-generated method stub
importShapefiletest isf = new importShapefiletest();
isf.importShapfile();
}}

3.3導入OSM
導入OSM的過程和導入shapefile差異不大,舊版Neo4j Spatial 提供了批量讀入的接口BatchInserter,可以加快大文件的導入。具體JavaDoc請參閱打包后的文檔。

package edu.sirc.gis.data;import java.io.File; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map;
import org.neo4j.gis.spatial.osm.OSMImporter; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.kernel.EmbeddedGraphDatabase; import org.neo4j.kernel.impl.batchinsert.BatchInserter; import org.neo4j.kernel.impl.batchinsert.BatchInserterImpl;
public class importOSMTest {
/** * @param args */ //import osm file into the default db for server . private String databasepath="/home/vent/environment/neo4j/data/graph.db"; private String osmPath="/home/vent/Downloads/"; private static final Map<String, String> NORMAL_CONFIG = new HashMap<String, String>(); static { NORMAL_CONFIG.put( "neostore.nodestore.db.mapped_memory", "50M" ); NORMAL_CONFIG.put( "neostore.relationshipstore.db.mapped_memory", "120M" ); NORMAL_CONFIG.put( "neostore.propertystore.db.mapped_memory", "150M" ); NORMAL_CONFIG.put( "neostore.propertystore.db.strings.mapped_memory", "200M" ); NORMAL_CONFIG.put( "neostore.propertystore.db.arrays.mapped_memory", "0M" ); NORMAL_CONFIG.put( "dump_configuration", "false" ); } private void importOSM() throws Exception {
</span><span class="typ">OSMImporter</span><span class="pln"> osmIm </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">OSMImporter</span><span class="pun">(</span><span class="str">"FUJIAN"</span><span class="pun">);</span><span class="pln"> </span><span class="typ">Map</span><span class="pun">&</span><span class="pln">lt</span><span class="pun">;</span><span class="typ">String</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pun">&</span><span class="pln">gt</span><span class="pun">;</span><span class="pln"> config </span><span class="pun">=</span><span class="pln"> NORMAL_CONFIG</span><span class="pun">;</span><span class="pln"> </span><span class="lit">@SuppressWarnings</span><span class="pun">(</span><span class="str">"deprecation"</span><span class="pun">)</span><span class="pln"> </span><span class="com">//BatchInserter baIns = new BatchInserterImpl(osmPath,config);</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> dataset </span><span class="pun">=</span><span class="str">"/home/vent/Downloads/Fujian.osm"</span><span class="pun">;</span><span class="pln"> </span><span class="com">//osmIm.importFile(baIns,dataset,false);</span><span class="pln"> </span><span class="typ">GraphDatabaseService</span><span class="pln"> db </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">EmbeddedGraphDatabase</span><span class="pun">(</span><span class="pln">databasepath</span><span class="pun">);</span><span class="pln"> osmIm</span><span class="pun">.</span><span class="pln">importFile</span><span class="pun">(</span><span class="pln">db</span><span class="pun">,</span><span class="pln"> dataset</span><span class="pun">);</span><span class="pln"> osmIm</span><span class="pun">.</span><span class="pln">reIndex</span><span class="pun">(</span><span class="pln">db</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln"> db</span><span class="pun">.</span><span class="pln">shutdown</span><span class="pun">();</span><span class="pln">
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
importOSMTest iOSM = new importOSMTest();
iOSM.importOSM();
}}

下講會講述Neo4j Spatial與GeoServer 的集成,以及與Neo4j Server的集成。
[8]Neo4j Spatial http://nowiki.neo4j.org/content/Neo4j_Spatial
[9] OpenGIS® Simple Features Specification For SQL
[10]Vicknair, C. et al. 2010. A Comparison of a Graph Database and a Relational Database. In Proceedings of the 48th annual Southeast regional conference
[11]Apache Lucene http://lucene.apache.org/core/
[12]R-tree http://en.wikipedia.org/wiki/R-tree
[13]GiST http://en.wikipedia.org/wiki/GiST
[14]空間數據庫索引技術 郭薇 郭菁 上海交通大學出版社 P104-105 2006
[15]EGit http://www.eclipse.org/egit/
[16]Maven Integration (m2e) http://eclipse.org/m2e/