neo4j spatial contain search

2019-01-18 17:00发布

问题:

i'm trying to develop a web service able to give me back the name of the administrative area that contains a given gps position.

I have already developed a java application able to insert some polygons (administrative areas of my country) in neo4j using spatial plugin and Java API. Then, giving a gps position, i'm able to get the name of the polygon that contains it.

Now i'm trying to do the same using REST API of Neo4j (instead of java api) but i'm not able to find any example.

So my questions are:

1) Is possible to insert polygons in Neo4j using REST API (if i well understood is possible using WKT format) ?

2) is possible to execute a spatial query that finds all polygons that contain a given gps position ?

thanks, Enrico

回答1:

The answer to both of your questions is yes. Here are example steps that use REST and Cypher.

1) Create your spatial layer and index (REST). In this example, my index is named 'test' (a layer of the same name and base spatial nodes will be created), and the name of the property on my nodes that will contain the wkt geometry information is 'wkt'.

POST http://localhost:7474/db/data/index/node {"name":"test", "config":{"provider":"spatial", "wkt":"wkt"}}

2) Create a node (Cypher). You can have labels and various properties. The only part that Neo4j Spatial cares about is the 'wkt' property. (You could do this step with REST.)

CREATE (n { name : "Fooville", wkt : "POLYGON((11.0 11.0, 11.0 12.0, 12.0 12.0, 12.0 11.0, 11.0 11.0))" })

3) Add the node to the layer. You can do this by adding the node to the index or to the layer, but there is an important difference. If you add it to the index, a copy node containing only the geometry data will be created, and that will be added to the layer. Querying via Cypher will return your original node, but querying via REST or Java will return the copy node. If you add the node directly to the layer, then you must take an extra step if you want to be able to query with Cypher later. In both cases you will need the URI of the node, the last element of which is the Neo4j node number. In the example below, I assume the node number is 4 (which it will be if you do this example on a fresh, empty database).

Method 1:

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

To make this node searchable via Cypher, add the node number to the node as a user 'id' property. (You could do this with REST.)

START n = node(4) SET n.id = id(n)

Method 2: Using this method will double your node count, double your WKT storage, and produce differing results when querying via REST vs Cypher.

POST http://localhost:7474/db/data/index/node/test {"value":"dummy","key":"dummy","uri":"http://localhost:7474/db/data/node/4"}

3) Run your query. You can do a query in REST or Cypher (assuming you conditioned the nodes as described above). The Cypher queries available are: 'withinDistance', 'withinWKTGeometry', and 'bbox'. The REST queries available are: 'findGeometriesWithinDistance', 'findClosestGeometries', and 'findGeometriesInBBox'. It's interesting to note that only Cypher allows you to query for nodes within a WKT geometry. There's also a difference in REST between the findClosestGeometries and findGeometriesWithinDistance that I don't yet understand, even though the arguments are the same. To see how to make the REST calls, you can issue these commands:

POST http://localhost:7474/db/data/ext/SpatialPlugin/graphdb/findGeometriesWithinDistance
POST http://localhost:7474/db/data/ext/SpatialPlugin/graphdb/findClosestGeometries
POST http://localhost:7474/db/data/ext/SpatialPlugin/graphdb/findGeometriesInBBox

The Cypher queries are: (replace text between '<>', including the '<>', with actual values)

START n = node:<layer>("withinDistance:[<y>, <x>, <max distance in km>]")
START n = node:<layer>("withinWKTGeometry:POLYGON((<x1> <y1>, ..., <xN> <yN>, <x1> <y1>))")
START n = node:<layer>("bbox:[<min x>, <max x>, <min y>, <max y>]")

I have assumed in all of this that you are using a longitude/latitude coordinate reference system (CRS), so x is longitude and y is latitude. (This preserves a right-handed coordinate system in which z is up.)