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.

Share this post

Comments