Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
01-03-2022 07:19 PM
Hi all,
Currently I have a lot of positional data (include lat and long) representing millions of nodes.
Original plan was to use bounding box query to put those nodes from above into clusters/region.
I realized there are only 2 options, a)spatial bounding box search and b)spatial distance searches.
There is no option for polygons which I have available from postgreSQL.
Is there a way to use polygon shapes/areas/length to do spatial grouping of nodes into regions? Any suggestions will be appreciated.
01-04-2022 08:55 AM
You can get the same effect of an index-backed within-polygon search by first converting the polygon to a bounding box, searching and then filtering by the original polygon. This requires two additional functions:
I discussed this approach in the GraphConnect 2018 presentation. I covered it in a little more detail in a followup meeting, which you can see in the video at All About Neo4j Spatial (Neo4j Online Meetup #44) - YouTube.
In that video I had written the two functions in the namespace amanzi.*
, however, since then we have created a newer library called spatial-algorithms
that has two functions:
spatial.boundingBox
spatial.algo.withinPolygon
You can find this library at GitHub - neo4j-contrib/spatial-algorithms: Spatial algorithms for both cartesian and geographic data
01-04-2022 10:11 PM
Hi @craig.taverner,
Thanks for pointing me in the right direction.
Now, I am creating relationships between nodes: Position and nodes:Region using the bounding box method.
match (r:region {region_name: '12 Ulu'}
match (p:position {deviceid: 2284} where point.withinBBox(p.positions_point, r.first_coor, r.last_coor)
call apoc.create.relationship(p, "IN")
r.first_coor, r.last_coor and p.positions_point all have the format point({srid:4326,x:104,y:2.97})
The code snippet has provided some errors, so do correct me if I am wrong.
My question is how to use the spatial.boundingBox or spatial.algo.withinPolygon to incorporate into the above query.
Any suggestions are welcomed.
01-05-2022 09:41 AM
Are r.first_coor
and r.last_coor
really the bottom left and top right of the polygon? The names make me think they are just the first and last coordinates of the polygon.
Do you perhaps have a list of coordinates for the entire polygon, because that is what you really need. For example, I could imagine you have a r.coordinates
which is an array of point
instances. Then you could do the following:
MATCH (r:region {region_name: '12 Ulu'}
WITH spatial.boundingBox(r.coordinates) as bbox
MATCH (p:position {deviceid: 2284} where point.withinBBox(p.positions_point, bbox.min, bbox.max)
CREATE (p)-[:IN]->(r)
I do not know why you wanted to use APOC to create relationships, so I replaced that with normal Cypher.
01-05-2022 06:57 PM
Yes r.first_coor and r.last_coor represent the min and max points of the polygon.
Currently I have polygon data type, which is long list of coordinates.
I have also looked into the github link and checked all the latest versions, using the link below.
There is no version for neo4j v4.4 which is what I am currently using.
I have installed the latest plugin spatial-algorithms-algo-0.2.5-neo4j-4.2.11.jar but when I try to find the spatial.algo.withinPolygon
within the neo4j browser, it is unable to find it.
call dbms.procedures()
yield name where name starts with 'spatial.algo.withinPolygon'
return name
Is there a version of spatial algorithms meant for neo4j 4.4?
01-09-2022 01:17 PM
I took a look at this over the weekend, and there is no spatial-algorithms
release for Neo4j 4.3 or Neo4j 4.4. So I did a test port to 4.3, but there are some changes in the kernel relating to cursor closing that has prevented completion of this port. I'll see if I can get some support to fix that, and then port to 4.4 as well later.
The other option you have is to try extracting just the withinPolygon
function or try use the older version from the spatial3d
library.
01-11-2022 05:18 PM
Hi @craig.taverner ,
I appreciate that you looked into my issue regarding the spatial-algorithms.
Personally, I think I will wait for more news on the fix. I honestly have no idea how to extract the withinPolygon and since my organization still plans on using the latest Neo4j 4.4, I do not think trying the older version of spatial3d library would be of any use either.
Lastly, I was hoping if there any additional resources on how to use withinPolygon and other use cases for it, utilizing Python drivers to display onto Neomap or into OpenStreetMap. Other than the sources listed below:
Any suggestions are welcome,
01-15-2022 10:37 AM
I have managed to port this library to Neo4j 4.4. See the release at Release Spatial Algorithms 0.2.5-neo4j-4.4.3 · neo4j-contrib/spatial-algorithms · GitHub
The main challenge was the preceding port to Neo4j 4.3, which involved some bigger algorithm changes to cope with a change in behaviour in the Neo4j kernel. But once that was done, porting to Neo4j 4.4 was trivial.
Regarding documentation of withinPolyon, there is only the test code at spatial-algorithms/UserDefinedFunctionsTest.java at master · neo4j-contrib/spatial-algorithms · GitH...
01-19-2022 02:50 AM
Hi @craig.taverner ,
I have tried to import the jar file in the link you provided below.
Unfortunately, when I restarted my Neo4j 4.4.11 desktop application to apply the changes, it refused to connect to my Neo4j db instance
A coworker of mine who uses Neo4j 4.4.12 desktop application was able to connect to Neo4j db instance after importing the plugin, however it still produces 0 results using the query below to check
call dbms.procedures()
yield name where name starts with 'spatial.algo.withinPolygon'
return name
That is the latest update I have for using the spatial algorithms
As a workaround, I currently using this function
match (n:Node)
call spatial.intersects('geom',n)
yield Node return node.name
The below function is what I use to create the node
unwind [{name:'a',latitude:0.79157,longitude:101.3333}] as point
merge (n:Node{name:point.name,
latitude:point.latitude,
longitude:point.longitude})
Note, I have imported shape file prior to this to extract my POLYGON data
Any suggestions would be appreciated
01-19-2022 06:22 AM
A few comments:
spatial.algo.withinPolygon()
function is a function not a procedure, so you will not find it using dbms.procedures()
but need to look using dbms.functions()
.spatial.intersects()
is provided by the spatial
library, which itself is not ported to Neo4j 4.4. The latest release of that library is for 4.2.01-19-2022 11:28 PM
Hi @craig.taverner,
Appreciate the comments, for now I am just using the link below
I was able to call the function spatial.algo.withinPolygon() successfully.
But I am unclear as to how to use the information in my imported shape file and using it with the spatial.algo function. and I keep getting the error below
My conclusion is that I do not understand the logic to access the data for my SpatialLayer node created.
The below code was used to add the node
call spatial.addWKTLayer('geom','geom');
call spatial.importShapefileToLayer('geom','import/shapefile/admin_region.shp');
Finally, I wish to create a cypher to use the spatial.algo.withinPolygon to create a relationship between my SpatialLayer node with my nodes
01-20-2022 11:49 AM
OK. So it looks like you are using two libraries together. This means you need to understand the different internal structures of the geometries as understood by those two libraries in order to pass data from one to the other. A polygon in the spatial library could be a WKT string, while a polygon in the algorithms library is always a list of points, and it will never understand WKT, so you need to convert it to a list of points.
Also, the query you are using to get the polygon will not work because you are looking for a geometry on the SpatialLayer
node which never has geometries, so s.geom
will always have value null
, and that is why you got that error.
The SpatialLayer node is just the root of a data tree containing all the data you want. You can traverse that tree using Cypher, but that is not the intention. It is intended to be searched using the spatial procedures provided by the spatial
library.
While I could point out errors in the queries you provide here, I think in order to properly support you, I would need to know what the original data is that you imported, and what type of queries you are trying to perform? For example, it seems like you have two different types of data and want to use one to search the other. I could speculate further, but it would be better if you simply describe the situation here, and then I can give more comprehensive support.
For example, you could say:
Then I could describe a query that would work for this scenario.
01-20-2022 06:08 PM
Agreed @craig.taverner,
The situation is as you describe
We have polygons imported as WKT from, shapefiles
We have points imported as latitude/longitude properties of nodes
We want to find a particular polygon from the shapefile
And use it to find points(from the imported nodes) within the polygon
Lastly, the shapefiles I imported as WKT layer, has null values as shown below.
I notice the property values stored in the SpatialLayer node is in string and uses () brackets, and it cannot be treated as a list, I have tried using the apoc.convert.toList and it still converts to string and not as a list.
Hope that this helps. Is there any function or procedure that can help to convert info in one type of spatial library to spatial algo library.
Any suggestions are appreciated.
01-21-2022 09:11 AM
OK. I think there are two parts you are missing:
spatial.algo.withinPolygon
functionBefore I explain more about how to fix those two points, have you considered just using the spatial
library by itself? I mean store both polygons and points using that library, instead of mixing and matching two different ways of working with geospatial data? The advantage would be not having to worry about WKT conversion. The disadvantage would be slower searching for points because the spatial index used by the spatial
library is not nearly as well optimized as the spatial index used by native Neo4j points.
Anyway, back to the main answer. The first thing is to find the polygon. The Cypher expression you used would find all kinds of nodes in the graph, only some of which are actual data nodes, which is why you are getting null
values (you are finding index nodes, and anything connected to the layer, even config setting nodes). You could write a more complex Cypher expression to avoid this, but that would be missing the point of the spatial library. It comes with a number of procedures for spatial search. I don't know what polygon you are looking for, but can suggest a few functions, like spatial.withinDistance
, or spatial.intersects
. Then you will have the polygon (or polygons) with WKT geometries, and can use that for the point search.
The second thing would be to convert the WKT into points. This is not trivial, because there is no existing function I can see that does this job directly. The spatial library has a function spatial.asGeometry
which converts the WKT into an internal Neo4j geometry type, but no other code understands that type. You need a function that generates the list of points from that type. This would be very easy to write, but currently does not exist in either of the libraries you are trying to use. It could probably be added to either one, or written by yourself.
All the sessions of the conference are now available online