Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update to: Adding node to Neo4j Spatial Index

Tags:

neo4j

cypher

I'm hoping someone can provide some updated clarification on adding nodes to Spatial. The best instructions I can find is:

Neo4j Spatial 'WithinDistance' Cypher query returns empty while REST call returns data

However it's almost 2 years old and has some contradictory information with an acknowledged bug (https://github.com/neo4j-contrib/spatial/issues/106), which appears to still be open.

I also found this tutorial:

http://mattbanderson.com/setting-up-the-neo4j-spatial-extension/

Which says we should add the node to the layer AND insert the Neo4j ID# into the node as a property, but NOT insert the node to the geom index.

My main priority here is that I be able to query via Cypher (within the browser) but we will eventually want to be able to query via REST as well. So, ideally i'd like to insert the nodes in such a way that we can do both.

So, my questions are:

1) What are the correct steps here to allow querying via both REST and Cypher?

2) If I call /addSimplePointLayer and then /index/node to add the Spatial index (both via cURL or REST), can I use LOAD CSV to insert nodes and be able to query Spatial Plugin via both REST and Cypher?

3) If I am using REST to insert my nodes, what calls (and in what order) would I need to make in order to ensure that I can query via both REST and Cypher (web browser)?

Thanks, I'm looking forward to getting this all worked out!!

like image 490
Brooks Avatar asked Apr 09 '15 22:04

Brooks


People also ask

Can u relabel node in Neo4j?

You can change the nodes associated with a label but you can't change the type of a relationship. Conceptually, if you take your chicken out of one coop and put it in another you haven't altered the substance of the chicken.

How do I add multiple nodes in Neo4j?

The create clause of Neo4j CQL is also used to create multiple nodes at the same time. To do so, you need to pass the names of the nodes to be created, separated by a comma.

Does Neo4j support indexing?

Neo4j will automatically pick up and start using the index once it has been created and brought online. There are multiple index types available: b-tree (deprecated), fulltext, lookup, and text index types.

What does indexing speed up in Neo4j?

In neo4j you can create index for both property and nodes. Indexing is data structure that helps faster performance on retrieval operation on database.


1 Answers

question 1

You first need to initialize once a layer and create the spatial index using the REST calls:

POST /db/data/ext/SpatialPlugin/graphdb/addSimplePointLayer HTTP/1.1
Host: localhost:7474
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{ 
    "layer" : "geom", 
    "lat" : "lat", 
    "lon" : "lon" 
}

and:

POST /db/data/index/node/ HTTP/1.1
Host: localhost:7474
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{ 
    "name" : "geom", 
    "config" : { 
        "provider" : "spatial", 
        "geometry_type" : "point", 
        "lat" : "lat", 
        "lon" : "lon" 
    } 
}

Create a node with lon/lat properties using Cypher via the transactional endpoint:

POST /db/data/transaction/commit HTTP/1.1
Host: localhost:7474
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{
  "statements" : [ 
  {
    "statement" : "create (city:City {data}) return id(city)",
    "parameters" : {
      "data" : {
        "name" : "MyTown",
        "lon": 15.2,
        "lat": 60.1
      }
    }
  } 
  ]
}

and add it to the spatial index - be sure to adopt the node id with the id of the node returned from the previous request:

POST /db/data/ext/SpatialPlugin/graphdb/addNodeToLayer HTTP/1.1
Host: localhost:7474
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{ 
    "layer": "geom", 
    "node": "http://localhost:7474/db/data/node/<my_nodeid_goes_here>" 
}

In order to enable Spatial play nice with Cypher a hack is required: every geo-indexed node should carry a property called id with the value of the node id. This can be accomplished with a simple cypher statement (the example below does this for all City nodes):

POST /db/data/transaction/commit HTTP/1.1
Host: localhost:7474
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{ 
    "statements" : [ 
        { "statement" : "match (n:City) set n.id=id(n)" } 
    ] 
}

With that in place you can use Cypher for geo queries, e.g.:

POST /db/data/transaction/commit HTTP/1.1
Host: localhost:7474
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{
  "statements" : [ 
  {
    "statement" : "start city = node:geom('withinDistance:[60.1,15.2, 100.0]') return city",
    "parameters" : {}
  } 
  ]
}

NB: for withinDistance you have to specify lat,lon, distanceInKm.

question 2

As described above you need to have a separate REST call for adding a node to the spatial index. This is currently not possible with Cypher directly. As a workaround use LOAD CSV to create the nodes with lon/lat properties. In a preprocessing step run a statement like MATCH (n:City) where not has(n.id) set n.id = id(n) return id(n) as id. This will set the id properties (the hack described above) and returns a list of ids of the new nodes. For each of them emit the REST call to add a node to the geo index.

question 3

Has been answered already above :-)

like image 152
Stefan Armbruster Avatar answered Nov 09 '22 11:11

Stefan Armbruster