Neo4j Spatial ‘WithinDistance’ Cypher query returns empty while REST call returns data

I investigated this, and it is related to an issue we have seen a few times. There is an inconsistency in the design of the spatial library in that there are two ways to add a node to the spatial index. The one is to add it to the Layer (using the addNodeToLayer REST call), and this uses the underlying Java API which directly connects the node into the RTree as part of the same graph. The other is to create a proxy node in the index graph so that your domain graph is not connected to the index graph. This second approach is only taken by the IndexProvider interface (using the /db/data/index/node/geom REST call).

If you call both methods, the node is added twice, once directly and once by proxy. The problem is that the Cypher withinDistance index query accesses only the IndexProvider interface, and will only return nodes that are NOT also connected to the index. So if you add the node in both ways, it will not be returned.

So you need to add it only one of the two ways. I did not see in your original email any mention of addNodeToLayer, so I suspect that SDN might be calling addNodeToLayer (perhaps Michael can comment), in which case you cannot use the cypher call.

During my testing, I was able to manually remove the one index relationship using Cypher like this:

START n=node(13065) MATCH (n)<-[r:RTREE_REFERENCE]-() DELETE r

Replace the number 13065 with your node id for the original node.

I did the following in the neo4j browser (in 2.1.2):

:POST /db/data/ext/SpatialPlugin/graphdb/addSimplePointLayer { "layer":"geom", "lat":"lat", "lon":"lon" }
:POST /db/data/index/node/ {"name":"geom", "config":{"provider":"spatial", "geometry_type":"point","lat":"lat","lon":"lon"}}
:POST /db/data/node {"lat":60.2,"lon":15.1,"RaceName":"Parador Es Muy Caliente"}
:POST /db/data/index/node/geom {"value":"dummy","key":"dummy", "uri":"http://localhost:7474/db/data/node/13071"}

This created a graph with the node not directly connect to the index. In this case the REST call ‘findGeometriesWithinDistance’ does not work (uses standard Java API), while the cypher ‘withinDistance’ does work. I tested with this command:

start n = node:geom("withinDistance:[60.2,15.1,100.0]") return n

Note that unfortunately this API puts the order as lat,lon, instead of the more standard lon,lat.

Then I also added to the layer (ie. add directly to the index graph):

:POST /db/data/ext/SpatialPlugin/graphdb/addNodeToLayer {"layer":"geom", "node":"http://localhost:7474/db/data/node/13071"}

Now when I search with the cypher command I still get the same correct answer, but when I search with the REST command:

:POST /db/data/ext/SpatialPlugin/graphdb/findGeometriesWithinDistance {"layer":"geom","pointX":15.0,"pointY":60.0,"distanceInKm":100.0}

I find this returns the proxy node instead of the original node.

Leave a Comment