Distance Queries with Neo4j Spatial
One great feature of Neo4j spatial is that it provides an implementation of the generic Index
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.