Insights into what moves us. Contributions from the Structr team and guests. The Structr Blog

Axel Morgner
28. July 2012

Distance Queries with Neo4j Spatial

One great feature of Neo4j spatial is that it provides an implementation of the generic Index interface. That makes it quite easy to add f.e. a distance search to your project:

Setup

Add neo4j-spatial dependency to your project's pom.xml. (For details see https://github.com/neo4j/spatial)

<dependency>
    <groupId>org.neo4j</groupId>
    <artifactId>neo4j-spatial</artifactId>
    <version>0.9-SNAPSHOT</version>
</dependency>

Properties for Latitude and Longitude

Define which properties hold the coordinates (property keys here are "lat", "lon"):

final Map<String, String> config = new HashMap<String, String>();
config.put(LayerNodeIndex.LAT_PROPERTY_KEY, "lat");
config.put(LayerNodeIndex.LON_PROPERTY_KEY, "lon");
config.put(SpatialIndexProvider.GEOMETRY_TYPE, LayerNodeIndex.POINT_PARAMETER);

Layer Index

Create a layer index:

LayerNodeIndex layerIndex = new LayerNodeIndex("layerIndex", graphDb, config);

Add your nodes to the index (note: nodes added to the layer index must have the lat and lon properties set.

layerIndex.add(dbNode, "", "");

Query

Now you can use the standard index query methods to get a list of nodes within a given distance from a given location, sorted by the (ascending) distance from that point:

IndexHits hits  = index.query(LayerNodeIndex.WITHIN_DISTANCE_QUERY, params);

Double coords = new Double[]{ 10.415039d, 51.151786d };
Map<String, Object> params = new HashMap<String, Object>();

params.put(LayerNodeIndex.POINT_PARAMETER, coords.toArray());
params.put(LayerNodeIndex.DISTANCE_IN_KM_PARAMETER, dist);

IndexHits hits  = index.query(LayerNodeIndex.WITHIN_DISTANCE_QUERY, params);

You get back an Iterable with SpatialRecordHits. To get your original nodes out of it, resolve them by the id property:

for (Node spatialNode : hits) {

    Node dbNode = graphDb.getNodeById((Long) spatialNode.getProperty("id"));

    // do something
}

The default coordinate system used is WGS84. Internally, the search is a traversal within an R-Tree, a data structure optimized for spatial queries.