I created a spatial index in neo4j but when searching for nearby places I only get one result.
My query is:
START n=node:geom('withinDistance:[63.36, 10.35, 50.0]') RETURN n
And I have 3 nodes in the spatial index with this coords:
- Node 1 lat,lon: 63.3654, 10.3578
- Node 2 lat,lon: 63.3654, 10.3577
- Node 3 lat,lon: 63.3654, 10.3578 (same node 1)
Theoretically the three nodes are in the same area.
Any idea?
UPDATE
I performed these steps to use spatial (all executed from neo4j browser -> rest api)
1) Index creation
:POST /db/data/index/node/
{
"name" : "geom",
"config" : {
"provider" : "spatial",
"geometry_type" : "point",
"lat" : "lat",
"lon" : "lon"
}
}
2) Nodes creation (all in the same way)
:POST /db/data/node
{
"name":"Franciscatos Pizza",
"lat": 63.3654,
"lon": 10.3578
}
3) Node to spatial index
:POST /db/data/index/node/geom
{
"value":"dummy",
"key":"dummy"
"uri":"http://localhost:7474/db/data/node/8"
}
4) Node to layer
:POST /db/data/ext/SpatialPlugin/graphdb/addNodeToLayer
{
"layer":"geom",
"node":"http://localhost:7474/db/data/node/8"
}
Any API response are OK and all nodes indexed contain the :RTREE_REFERENCE relationship.
Depending on the distance parameter in the query, this returns me different nodes, but always one...
Darios,
First thing, don't do step 3). Steps 3) and 4) are somewhat redundant, but step 3) makes a copy of the geometry information in the node and creates a second node that is stored into the layer. Instead, do this new step 3).
START n = NODE(8)
SET n.id = ID(n)
This Cypher code adds an 'id' parameter on the node that contains the Neo4j node number. Once you do this, you can use the Cypher spatial index query. Note that the first line will have a different node number each time. This 'id' property is self-referential.
Alternatively, do your step 3), but don't do step 4). But then you won't get what you expect if you do a REST geometry query.
See if your results improve.
Grace and peace,
Jim
PS.
Michael,
There's actually two competing approaches in play with spatial right now. If you use addNodeToLayer to add your node to a layer (as in step 4), the node is linked into the RTree graph directly and Cypher queries won't find the node. This is also true if you are using Java. You can query via REST using findGeometriesWithinDistance and findGeometriesInBBox.
If you use the 'add the node to the spatial index' method to add your node to a layer (as in step 3), it doesn't actually add your node to the layer. A new node is made that contains a copy of the geometry properties on the original node and an 'id' property that contains the Neo4j node number of the original node, and this copy node is added to the RTree graph. The 'spatial index' does not actually contain a list of nodes. It is an access point for the spatial extension code. When you do a Cypher spatial query, the spatial extension finds the copy nodes that satisfy the query, then dereferences the 'id' properties on each to build a return list of original nodes.
It's the lack of the 'id' property to dereference that causes Cypher spatial index queries to fail if you add a node to a layer using step 4) alone. By adding the 'id' property, the dereference succeeds, and you get results from your query.
The shapefile importer links nodes directly into the RTree, and if you want to be able to do Cypher spatial index queries, you need to add the 'id' property to each node as I described. The OSM importer builds related 'domain' and geometry nodes, but I don't think it makes them accessible to Cypher-based queries. If you add the 'id' property to each geometry node, then they will be.
I may have missed it, but I haven't seen anyone point out that if you use the 'add the node to the spatial index' method, that you just doubled the number of nodes you have, as well as doubled the number of geometry properties stored in your database. Since there is no relationship built between the original nodes and the copy nodes, there is no way to access the geometry properties in the copy nodes, so you can't really delete the geometry properties from the original nodes.
As a result, I find it more desirable to add my nodes to the RTree graph directly and make them queryable (queriable?) through the Cypher spatial index by adding self-referential 'id' properties.
As for deleting nodes, there is no REST SpatialPlugin method for removing a node from a layer. If you add the node to the RTree graph using the REST spatial index method, then the REST call
:DELETE /db/data/index/node/geom/{ID}
will remove the node from the RTree, but there is a catch. You must get the Neo4j node number of the copy node in order for this to work! Which you can't in any straightforward way. If you manage to obtain the node number of the copy node, it will remove it from the RTree, but the copy node is not deleted.
Somewhat ironically, if you add the node to the RTree using addNodeToLayer and don't add the 'id' property, the call to remove the node from the index removes the node from the RTree. If you add the self-referential 'id' property and then remove the node from the index, the node is deleted. So every approach is flawed.
I am using neo4j 2.3 and found that step 3) is useless but not step 4), also if you do not clone the id as property the query from cypher do not work anymore ( return no results )