Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
12-08-2022 09:11 PM
Hi,
We have a OSM data uploaded for San Diego. We also have housing data for which we've found longitudes and latitudes and have uploaded as nodes with corresponding spatial points.
How would one join this housing data with the OSM? I spent a while on Google trying to figure this out, but couldn't find much. It seems that you have your housing (label) node for each specific house and that you should be able to essentially create something akin to a point of interest with each house which will join to the map through an edge and a node, where it will join to the nearest edge (road) given the house's spatial coordinates. I'm not sure how to do this.
Here is script used for OSM import:
UNWIND $rows AS row
CREATE (p:PointOfInterest {name: row.names.local})
CREATE (g:Geometry)
SET g.location = point({latitude: toFloat(row.point[1]), longitude: toFloat(row.point[0]) })
CREATE (g)<-[:HAS_GEOMETRY]-(p)
SET g:Point
CREATE (t:Tags)
SET t += row.original_tags_dict
CREATE (p)-[:HAS_TAGS]->(t)
WITH *
CALL apoc.create.addLabels(p, [row.class, row.subclass]) YIELD node
RETURN COUNT(*) AS total
02-06-2023 11:37 AM
Are you thinking about importing the San Diego road network as well? That would allow you to model intersections and road segments in the graph. You could then identify the closest intersection to each point of interest or house/address, which would give you a fully connected graph. I've been playing around with data from Open Addresses for this. Here's the data model I'm using:
After adding point of interest and address nodes, I looked for the closest intersection node to each point of interest and address node like this:
MATCH (p:Address) WHERE NOT EXISTS ((p)-[:NEAREST_INTERSECTION]->(:Intersection)) WITH p LIMIT 100000 CALL { WITH p MATCH (i:Intersection) USING INDEX i:Intersection(location) WHERE point.distance(i.location, p.location) < 2000 WITH i ORDER BY point.distance(p.location, i.location) ASC LIMIT 1 RETURN i } WITH p, i MERGE (p)-[r:NEAREST_INTERSECTION]->(i) SET r.length = point.distance(p.location, i.location) RETURN COUNT(p)
Then for routing between addresses/pois:
MATCH (a:Address)-[:NEAREST_INTERSECTION]->(source:Intersection) WHERE a.full_address CONTAINS "410 E 5TH AVE SAN MATEO, CA" MATCH (poi:PointOfInterest)-[:NEAREST_INTERSECTION]->(dest:Intersection) WHERE poi.geometry_id = "w914450392@1" CALL apoc.algo.dijkstra(source, dest, "ROAD_SEGMENT", "length") YIELD weight, path WITH [ x in nodes(path) | {latitude: x.location.latitude, longitude: x.location.longitude}] AS route, weight AS totalDist RETURN *
Perhaps a similar approach might be useful? The code is currently split between these two GitHub repos:
* https://github.com/johnymontana/geospatial-graph-demos - Some examples of spatial search and routing with OSM data
* https://github.com/johnymontana/neo4j-osmnx-experiments - Importing OSM and OpenAddresses data into Neo4j
02-07-2023 12:45 PM
Are you planning to add the road network from OpenStreetMap as well? I've been playing around with this recently. Here's the data model I'm using (includes both points of interest and addresses from Open Addresses)
The road network models intersections, so for a fully connected graph I wanted to find the closest intersection for each point of interest or address:
MATCH (p:Address) WHERE NOT EXISTS ((p)-[:NEAREST_INTERSECTION]->(:Intersection)) WITH p LIMIT 100000 CALL { WITH p MATCH (i:Intersection) USING INDEX i:Intersection(location) WHERE point.distance(i.location, p.location) < 2000 WITH i ORDER BY point.distance(p.location, i.location) ASC LIMIT 1 RETURN i } WITH p, i MERGE (p)-[r:NEAREST_INTERSECTION]->(i) SET r.length = point.distance(p.location, i.location) RETURN COUNT(p)
Then, we can route between and point of address or address like this:
MATCH (a:Address)-[:NEAREST_INTERSECTION]->(source:Intersection) WHERE a.full_address CONTAINS "410 E 5TH AVE SAN MATEO, CA" MATCH (poi:PointOfInterest)-[:NEAREST_INTERSECTION]->(dest:Intersection) WHERE poi.geometry_id = "w914450392@1" CALL apoc.algo.dijkstra(source, dest, "ROAD_SEGMENT", "length") YIELD weight, path WITH [ x in nodes(path) | {latitude: x.location.latitude, longitude: x.location.longitude}] AS route, weight AS totalDist RETURN *
The code is currently split across two repos:
All the sessions of the conference are now available online