Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.neo4j-contrib:spatial:5.20.0'
}
dependencies {
implementation("com.github.neo4j-contrib:spatial:5.20.0")
}
<dependency>
<groupId>com.github.neo4j-contrib</groupId>
<artifactId>spatial</artifactId>
<version>5.20.0</version>
</dependency>
libraryDependencies += "com.github.neo4j-contrib" % "spatial" % "5.20.0"
:dependencies [[com.github.neo4j-contrib/spatial "5.20.0"]]
Neo4j Spatial is a library facilitating the import, storage and querying of spatial data in the Neo4j open source graph database.
This project's manual is deployed to the Neo4j Labs page.
Since version 5.19.0, the versioning of Neo4j Spatial is aligned with the versioning of Neo4j itself. This means that Neo4j Spatial 5.19.0 is build against Neo4j 5.19, and so on.
set up your database with the following configuration in your neo4j.conf
file:
dbms.security.procedures.unrestricted=spatial.*
NOTE: If you're concerned about the security risks of unrestricted access, we recommend reviewing the code to assess
the level of risk for your use case. For example, the method
IndexAccessMode.withIndexCreate
grants index
creation capabilities within the security model. This allows users without index creation privileges to generate the
required spatial support indexes. This behavior was not intentionally designed to bypass security but was necessary
due to Neo4jās security model, where procedures with WRITE mode are not permitted to create indexes.
As a result, this adjustment was required even in the Community Edition of Neo4j.
Restart your Neo4j server.
CALL spatial.procedures
in the Neo4j browser to see the available spatial procedures.The key concepts of this library include:
GeometryEncoder
).
Built-in encoders include:
Point
)Some key features include:
START node=node:geom({query})
The current index is an RTree index, but it has been developed in an extensible way allowing for other indices to be added if necessary. The spatial queries implemented are:
The simplest way to build Neo4j Spatial is by using maven. Just clone the git repository and run
mvn install
This will download all dependencies, compiled the library, run the tests and install the artifact in your local
repository.
The spatial plugin will also be created in the target
directory, and can be copied to your local server using
instructions from the installation section.
The primary type that defines a collection of geometries is the Layer. A layer contains an index for querying. In addition, a Layer can be an EditableLayer if it is possible to add and modify geometries in the layer. The next most important interface is the GeometryEncoder.
The DefaultLayer is the standard layer, making use of the WKBGeometryEncoder for storing all geometry types as byte[] properties of one node per geometry instance.
The OSMLayer is a special layer supporting Open Street Map and storing the OSM model as a single fully connected graph. The set of Geometries provided by this layer includes Points, LineStrings and Polygons, and as such cannot be exported to Shapefile format, since that format only allows a single Geometry per layer. However, OMSLayer extends DynamicLayer, which allow it to provide any number of sub-layers, each with a specific geometry type and in addition based on an OSM tag filter. For example, you can have a layer providing all cycle paths as LineStrings, or a layer providing all lakes as Polygons. Underneath these are all still backed by the same fully connected graph, but exposed dynamically as apparently separate geometry layers.
Spatial data is divided in Layers and indexed by a RTree.
GraphDatabaseService database = new GraphDatabaseFactory().newEmbeddedDatabase(storeDir);
try{
ShapefileImporter importer = new ShapefileImporter(database);
importer.importFile("roads.shp","layer_roads");
} finally {
database.shutdown();
}
If using the server, the same can be achieved with spatial procedures (3.x only):
CALL spatial.addWKTLayer('layer_roads', 'geometry')
CALL spatial.importShapefileToLayer('layer_roads', 'roads.shp')
This is more complex because the current OSMImporter class runs in two phases, the first requiring a batch-inserter on the database. There is ongoing work to allow for a non-batch-inserter on the entire process, and possibly when you have read this that will already be available. Refer to the unit tests in classes TestDynamicLayers and TestOSMImport for the latest code for importing OSM data. At the time of writing the following worked:
OSMImporter importer = new OSMImporter("sweden");
Map<String, String> config = new HashMap<String, String>();
config.put("neostore.nodestore.db.mapped_memory", "90M" );
config.put("dump_configuration", "true");
config.put("use_memory_mapped_buffers", "true");
BatchInserter batchInserter = BatchInserters.inserter(new File(dir), config);
importer.importFile(batchInserter, "sweden.osm", false);
batchInserter.shutdown();
GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase(dir);
importer.reIndex(db, 10000);
db.shutdown();
GraphDatabaseService database = new GraphDatabaseFactory().newEmbeddedDatabase(storeDir);
try {
SpatialDatabaseService spatialService = new SpatialDatabaseService(database);
Layer layer = spatialService.getLayer("layer_roads");
SpatialIndexReader spatialIndex = layer.getIndex();
Search searchQuery = new SearchIntersectWindow(new Envelope(xmin, xmax, ymin, ymax));
spatialIndex.executeSearch(searchQuery);
List<SpatialDatabaseRecord> results = searchQuery.getResults();
} finally {
database.shutdown();
}
If using the server, the same can be achieved with spatial procedures (3.x only):
CALL spatial.bbox('layer_roads', {lon: 15.0, lat: 60.0}, {lon: 15.3, lat: 61.0})
Or using a polygon:
WITH 'POLYGON((15.3 60.2, 15.3 60.4, 15.7 60.4, 15.7 60.2, 15.3 60.2))' AS polygon
CALL spatial.intersects('layer_roads', polygon) YIELD node
RETURN node.name AS name
For further Java examples, refer to the test code in the LayersTest and the TestSpatial classes.
For further Procedures examples, refer to the code in the SpatialProceduresTest class.
IMPORTANT: Examples in this readme were originally tested with GeoServer 2.1.1. However, regular testing of new releases of Neo4j Spatial against GeoServer is not done, and so we welcome feedback on which versions are known to work, and which ones do not, and perhaps some hints as to the errors or problems encountered.
Each release of Neo4j Spatial builds against a specific version of GeoTools and should then be used in the version of GeoServer that corresponds to that. The list of releases below starting at Neo4j 2.0.8 were built with GeoTools 9.0 for GeoServer 2.3.2, but most release for Neo4j 3.x were ported to GeoTools 14.4 for GeoServer 2.8.4.
For the port to Neo4j 4.0 we needed to upgrade GeoTools to 24.x to avoid bugs with older GeoTools in Java 11. This also required a complete re-write of the Neo4jDataStore and related classes. This has not been tested at all in any GeoTools enabled application, but could perhaps work with GeoServer 2.18.
mvn clean install
target/xxxx-server-plugin.zip
and the Neo4j libraries from your Neo4j download under $NEO4J_HOME/lib
into $GEOSERVER_HOME/webapps/geoserver/WEB-INF/lib
svn co https://svn.codehaus.org/geoserver/trunk geoserver-trunk
cd geoserver-trunk
mvn clean install
cd src/web/app
mvn jetty:run
$GEOSERVER_SOURCE/src/web/app/pom.xml
https://svn.codehaus.org/geoserver/trunk/src/web/app/pom.xml, add the
following lines under the profiles section:<profile>
<id>neo4j</id>
<dependencies>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-spatial</artifactId>
<version>5.26.0</version>
</dependency>
</dependencies>
</profile>
The version specified on the version line can be changed to match the version you wish to work with (based on the version of Neo4j itself you are using). To see which versions are available see the list at Neo4j Spatial Releases.
cd $GEOSERVER_SRC/src/web/app
mvn jetty:run -Pneo4j
For more info head over to Neo4j Wiki on uDig (This wiki is currently dead, but there appears to be a working mirror in Japan at http://oss.infoscience.co.jp/neo4j/wiki.neo4j.org/content/Neo4j_Spatial_in_uDig.html).
The server plugin provides access to the internal spatial capabilities using three APIs:
CALL spatial.procedures
During the Neo4j 3.x releases, support for spatial procedures changed a little, through the addition of various new capabilities. They were very quickly much more capable than the older REST API, making them by far the best option for accessing Neo4j remotely or through Cypher.
The Java API (the original API for Neo4j Spatial) still remains, however, the most feature rich, and therefor we recommend that if you need to access Neo4j server remotely, and want deeper access to Spatial functions, consider writing your own Procedures. The Neo4j 3.0 documentation provides some good information on how to do this, and you can also refer to the Neo4j Spatial procedures source code for examples.
git clone https://github.com/neo4j-contrib/spatial/spatial.git
cd spatial
mvn clean package
Some of the classes in Neo4j-Spatial include main() methods and can be run on the command-line. For example there are command-line options for importing SHP and OSM data. See the main methods in the OSMImporter and ShapefileImporter classes. Here we will describe how to set up the dependencies for running the command-line, using the OSMImporter and the sample OSM file two-street.osm. We will show two ways to run this on the command line, one with the java command itself, and the other using the 'exec:java' target in maven. In both cases we use maven to set up the dependencies.
git clone git://github.com/neo4j-contrib/spatial.git
cd spatial
mvn clean compile
mvn dependency:copy-dependencies
java -cp target/classes:target/dependency/* org.neo4j.gis.spatial.osm.OSMImporter osm-db two-street.osm
Note: On windows remember to separate the classpath with ';' instead of ':'.
The first command above only needs to be run once, to get a copy of all required JAR files into the directory target/dependency. Once this is done, all further java commands with the -cp specifying that directory will load all dependencies. It is likely that the specific command being run does not require all dependencies copied, since it will only be using parts of the Neo4j-Spatial library, but working out exactly which dependencies are required can take a little time, so the above approach is most certainly the easiest way to do this.
mvn exec:java -Dexec.mainClass=org.neo4j.gis.spatial.osm.OSMImporter -Dexec.args="osm-db two-street.osm"
Note that the OSMImporter cannot re-import the same data multiple times, so you need to delete the database between runs if you are planning to do that.