Examples

Importing a shapefile

Neo4j-Spatial includes a utility for importing ESRI Shapefile data. The ShapefileImporter will create a new Layer for each Shapefile imported, and will store each Geometry as WKB in a single property of a single node. All attributes of the Feature will be stored as additional properties of that node. For more information on how this is implemented, you can refer to the classes WKBGeometryEncoder. However, you do not need to know any of that to use this feature. Consider the simple code below.

ShapefileImporter importer = new ShapefileImporter(database);
importer.importFile("shp/highway.shp", "highway", StandardCharsets.UTF_8);

This code will import the layer 'highway' from the file 'shp/highway.shp' which is included in the source distribution. This layer will be indexed using an RTree and can therefore be queried using any of the supported spatial operations. See the example on querying layers below.

Importing an Open Street Map file

This is more complex because the current OSMImporter class runs in two phases, the first requiring a batch-inserter on the database. The 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. For example:

OSMImporter importer = new OSMImporter("map.osm");
importer.setCharset(StandardCharsets.UTF_8);
importer.importFile(db, "map.osm");
importer.reIndex(db);

This code will import the map.osm Open Street Map file, populating the database with a little over 200 geometries, including streets, buildings and points of interest.

Executing a spatial query

Assuming you imported the map.osm file as in the previous example, you can now perform spatial searches on the data. The following example will search within a rectangle for a whatever geometries it can find:

SpatialDatabaseService spatial = new SpatialDatabaseService(
		new IndexManager((GraphDatabaseAPI) graphDb, SecurityContext.AUTH_DISABLED));
try (Transaction tx = database.beginTx()) {
	Layer layer = spatial.getLayer(tx, "map.osm");
	LayerIndexReader spatialIndex = layer.getIndex();
	System.out.println("Have " + spatialIndex.count(tx) + " geometries in " + spatialIndex.getBoundingBox(tx));

	Envelope bbox = new Envelope(12.94, 12.96, 56.04, 56.06);
	List<SpatialDatabaseRecord> results = GeoPipeline
			.startIntersectWindowSearch(tx, layer, bbox)
			.toSpatialDatabaseRecordList();

	doGeometryTestsOnResults(bbox, results);
	tx.commit();
}

For more examples of query code, refer to the test code in the LayerTest and the SpatialTest classes. Also review the classes in the org.neo4j.gis.spatial.query package for the full range or search queries currently implemented.

Export a shapefile

The ESRI Shapefile that we imported in the first example above was actually created by Neo4j-Spatial. It is possible to use the results of a query, or a DynamicLayer, to create a new Shapefile using the ShapefileExporter. If we were to export the complete layer created from importing a shapefile, we would not achieve much, but we could use this capability to create shapefiles that are subsets of other layers, or that are created from data in another format.

SpatialDatabaseService spatial = new SpatialDatabaseService(
		new IndexManager((GraphDatabaseAPI) graphDb, SecurityContext.AUTH_DISABLED));
String wayLayerName;
try (Transaction tx = database.beginTx()) {
	OSMLayer layer = (OSMLayer) spatial.getLayer(tx, "map.osm");
	DynamicLayerConfig wayLayer = layer.addSimpleDynamicLayer(tx, Constants.GTYPE_LINESTRING);
	wayLayerName = wayLayer.getName();
	tx.commit();
}
ShapefileExporter shpExporter = new ShapefileExporter(database);
shpExporter.exportLayer(wayLayerName);

This example shows how we can import an OSM dataset, which contains data with a number of different Geometry types, and then by using a DynamicLayer to select for only geometries of type 'LineString', we can export all the OSM ways to a Shapefile. This is particularly important when you consider that ESRI Shapefile format does not allow more than one Geometry type per shapefile.

SpatialDatabaseService spatial = new SpatialDatabaseService(
		new IndexManager((GraphDatabaseAPI) graphDb, SecurityContext.AUTH_DISABLED));
Envelope bbox = new Envelope(12.94, 12.96, 56.04, 56.06);
List<SpatialDatabaseRecord> results;
try (Transaction tx = database.beginTx()) {
	Layer layer = spatial.getLayer(tx, "map.osm");
	LayerIndexReader spatialIndex = layer.getIndex();
	System.out.println("Have " + spatialIndex.count(tx) + " geometries in " + spatialIndex.getBoundingBox(tx));

	results = GeoPipeline
			.startIntersectWindowSearch(tx, layer, bbox)
			.toSpatialDatabaseRecordList();

	spatial.createResultsLayer(tx, "results", results);
	tx.commit();

}
ShapefileExporter shpExporter = new ShapefileExporter(database);
shpExporter.exportLayer("results");

This time we import the same OSM model, but query for all geometries inside an envelope, and export that to a new Shapefile.

More Examples