Geospatial Knowledge Graphs: Querying Connected Spatial Entities with Neo4j and SPARQL
1. Introduction: Why Geospatial Data Needs Graph-Based Modeling

To build Geospatial Knowledge Graphs Neo4j SPARQL architectures effectively, traditional geographic information systems (GIS) rely heavily on relational databases. Traditional geographic information systems (GIS) rely heavily on relational databases, where spatial features are stored as records with attributes and geometries. This architecture works well for operations such as buffering, overlay analysis, spatial joins, and administrative boundary management. However, it becomes more challenging when a problem requires traversing many-to-many relationships across different spatial entities, organizational hierarchies, infrastructure dependencies, and external semantic datasets.
Consider an urban infrastructure network containing roads, water pipes, electricity substations, hospitals, administrative regions, and distribution warehouses. A conventional spatial database can determine which assets intersect a flood zone or fall within a particular district. Yet a more complex question may require tracing how a flooded power substation affects nearby hospitals, which depend on that substation, and which alternative facilities serve the affected communities. Answering this question requires combining geographic relationships with operational dependencies and domain-specific meaning.
Relational databases can represent these relationships through foreign keys, junction tables, recursive queries, and spatial joins. PostGIS, for example, remains highly capable of handling geometric calculations and spatial predicates. The limitation is not that relational systems cannot represent connected entities; rather, deeply interconnected data may require increasingly complex joins and recursive query logic, especially when relationship types change across multiple steps.
A geospatial knowledge graph provides another approach. It represents geographic features as nodes, their connections as edges, and their geographic and semantic characteristics as properties. Instead of relying exclusively on table joins, an analyst can traverse explicit relationships such as WITHIN, CONNECTS_TO, DEPENDS_ON, and SUPPLIES.
Two technologies are particularly useful in this architecture:
-
Neo4j and Cypher support property-graph modeling and graph traversal, making them suitable for querying connected spatial entities and operational dependencies.
-
SPARQL supports querying RDF-based knowledge graphs, enabling interoperability with linked data, geographic vocabularies, and semantic web datasets.
These technologies serve complementary roles. Neo4j provides a practical environment for traversing labeled nodes and relationships, while SPARQL allows applications to query semantic relationships represented using the Resource Description Framework (RDF). Combining them creates opportunities for a linked spatial data graph database architecture that connects geographic analysis with knowledge representation, discoverability, and cross-system data integration.
This guide develops an implementation workflow that models spatial features, imports geographic data into Neo4j, traverses administrative and infrastructure relationships with Cypher, and integrates an RDF/SPARQL endpoint for semantic web GIS integration.
2. Core Concepts: Modeling a Geospatial Knowledge Graph

A geospatial knowledge graph combines geographic entities, relationships, and semantic descriptions into a connected data model. Its structure is similar to a conventional knowledge graph, but it also preserves geographic coordinates, spatial identifiers, administrative membership, and references to geographic geometries.
Three components form the foundation.
| Component | Purpose | Example |
|---|---|---|
| Nodes | Represent identifiable entities | Hospital, warehouse, road junction, county |
| Relationships | Describe how entities are connected | LOCATED_IN, DEPENDS_ON, SUPPLIES |
| Properties | Store spatial and semantic attributes | Coordinates, asset type, identifier, capacity |
Suppose a distribution warehouse operates inside a county, receives electricity from a substation, and supplies three hospitals. A knowledge graph can represent this arrangement directly:
(County)
↑ PART_OF
(District)
↑ LOCATED_IN
(Warehouse) ── DEPENDS_ON ──> (Substation)
│
├── SUPPLIES ──> (Hospital A)
├── SUPPLIES ──> (Hospital B)
└── SUPPLIES ──> (Hospital C)
The important distinction is that these relationships are explicit. A query can follow connections from one asset to another without reconstructing every relationship through separate join tables.
2.1 Property graphs versus RDF graphs
Neo4j uses a labeled property graph model. Nodes and relationships have labels or types and can store properties such as asset identifiers, criticality ratings, or geographic points.
RDF, the Resource Description Framework, represents information as subject–predicate–object triples. For example:
@prefix ex: <https://data.example.org/id/> .
@prefix schema: <https://schema.org/> .
ex:warehouse-001
a ex:Warehouse ;
schema:name "Central Distribution Warehouse" ;
ex:dependsOn ex:substation-017 ;
ex:locatedIn ex:county-001 .
Each statement expresses a fact about a resource. SPARQL queries these RDF relationships using graph patterns. The W3C defines SPARQL 1.1 as a language for querying RDF data, including datasets exposed through middleware.
The models overlap conceptually but are not identical. A property graph may attach properties directly to relationships, whereas RDF represents additional facts about a relationship through further triples or RDF-star, depending on the implementation. A robust integration therefore needs deliberate mapping rules rather than a simple one-to-one conversion.
2.2 Spatial representation and coordinate reference systems
Spatial data can be stored in either system, but the supported geometry operations matter.
Neo4j’s built-in spatial functions support two-dimensional and three-dimensional POINT values, including geographic coordinates in WGS 84. Functions such as point.distance() calculate distances between compatible points, and point.withinBBox() checks bounding-box membership.
There is an important limitation: Neo4j’s native Cypher spatial type is a point, not a general-purpose polygon or line geometry. Storing a polygon as WKT text does not automatically enable polygon intersection or containment operations.
For advanced operations involving administrative polygons, road geometries, or complex spatial overlays, retain a spatial engine such as PostGIS or use a GeoSPARQL-capable RDF store. Neo4j can manage the relationships and dependencies that connect the resulting spatial entities.
3. Step-by-Step Implementation Guide
This tutorial builds an infrastructure knowledge graph using hypothetical administrative units, warehouses, hospitals, and power substations. The workflow assumes Neo4j is available and that your source data has been prepared as CSV files containing stable identifiers and coordinates.
Step 1: Structure spatial features and relationships
Start by separating the data into three logical datasets.
assets.csv
assetId,name,kind,longitude,latitude,adminId,criticality
A001,Central Warehouse,Warehouse,36.8219,-1.2921,C001,5
A002,East Substation,Substation,36.8500,-1.2800,C001,5
A003,City Hospital,Hospital,36.8100,-1.3000,C001,4
admin_units.csv
adminId,name,level,parentAdminId
C001,Central County,County,
D001,Central District,District,C001
dependencies.csv
dependencyId,fromAssetId,toAssetId,dependencyType,criticality
D001,A001,A002,Electricity,5
D002,A003,A001,MedicalSupplies,4
The direction of a relationship must have a consistent meaning. In this example, A001 DEPENDS_ON A002 means the warehouse depends on the substation. The relationship A003 DEPENDS_ON A001 means the hospital depends on the warehouse for medical supplies.
Use distinct identifiers for each entity, not just names. Names may change or be duplicated, while persistent identifiers support reliable matching across datasets.
A useful schema is:
-
(:Asset)for warehouses, hospitals, and substations. -
(:AdminUnit)for districts, counties, and other administrative areas. -
(:Asset)-[:DEPENDS_ON]->(:Asset)for operational dependencies. -
(:Asset)-[:LOCATED_IN]->(:AdminUnit)for administrative membership. -
(:AdminUnit)-[:PART_OF]->(:AdminUnit)for administrative hierarchies.
Store global identifiers such as externalUri alongside internal asset IDs whenever external semantic datasets will be integrated later.
Step 2: Import data into Neo4j using Cypher
Neo4j supports CSV ingestion through LOAD CSV, which reads each row as a collection of strings. Values such as coordinates and criticality ratings must therefore be converted into appropriate numeric types.
Create uniqueness constraints before importing the data:
CREATE CONSTRAINT asset_id IF NOT EXISTS
FOR (a:Asset)
REQUIRE a.assetId IS UNIQUE;
CREATE CONSTRAINT admin_unit_id IF NOT EXISTS
FOR (u:AdminUnit)
REQUIRE u.adminId IS UNIQUE;
Import the assets and their geographic points:
LOAD CSV WITH HEADERS
FROM 'file:///assets.csv' AS row
MERGE (a:Asset {assetId: row.assetId})
SET a.name = row.name,
a.kind = row.kind,
a.criticality = toInteger(row.criticality),
a.externalUri =
'https://data.example.org/id/' + row.assetId,
a.location = point({
longitude: toFloat(row.longitude),
latitude: toFloat(row.latitude)
});
Here, point() converts longitude and latitude into a native geographic point. Neo4j interprets these named coordinate fields as WGS 84 geographic coordinates, and distances between compatible WGS 84 points are returned in meters.
Next, import administrative units:
LOAD CSV WITH HEADERS
FROM 'file:///admin_units.csv' AS row
MERGE (u:AdminUnit {adminId: row.adminId})
SET u.name = row.name,
u.level = row.level;
Create the parent-child hierarchy separately:
LOAD CSV WITH HEADERS
FROM 'file:///admin_units.csv' AS row
WITH row
WHERE row.parentAdminId IS NOT NULL
AND row.parentAdminId <> ''
MATCH (child:AdminUnit {adminId: row.adminId})
MATCH (parent:AdminUnit {adminId: row.parentAdminId})
MERGE (child)-[:PART_OF]->(parent);
This makes administrative membership traversable regardless of how many hierarchy levels a dataset contains. It also avoids hard-coding a fixed county–district–subdistrict structure into every query.
Connect assets to administrative areas:
LOAD CSV WITH HEADERS
FROM 'file:///assets.csv' AS row
MATCH (a:Asset {assetId: row.assetId})
MATCH (u:AdminUnit {adminId: row.adminId})
MERGE (a)-[:LOCATED_IN]->(u);
Finally, create the dependency edges:
LOAD CSV WITH HEADERS
FROM 'file:///dependencies.csv' AS row
MATCH (source:Asset {assetId: row.fromAssetId})
MATCH (target:Asset {assetId: row.toAssetId})
MERGE (source)-[r:DEPENDS_ON {
dependencyId: row.dependencyId
}]->(target)
SET r.dependencyType = row.dependencyType,
r.criticality = toInteger(row.criticality);
Use the Neo4j import directory for local CSV files, or a trusted HTTPS source for remote files. Large datasets may warrant a bulk-import workflow rather than row-by-row Cypher ingestion.
Add a spatial index for nearby-asset queries:
CREATE POINT INDEX asset_location IF NOT EXISTS
FOR (a:Asset)
ON (a.location);
Neo4j point indexes support eligible distance and bounding-box predicates. Confirm index use with EXPLAIN or PROFILE, especially when querying large asset collections.
Step 3: Traverse administrative boundaries and network dependencies
Once the graph is populated, Cypher can follow relationships across multiple levels of the network.
A. Find the administrative hierarchy for an asset
MATCH (a:Asset {assetId: $assetId})
-[:LOCATED_IN]->(unit:AdminUnit)
MATCH path =
(unit)-[:PART_OF*0..10]->(ancestor:AdminUnit)
RETURN a.name AS asset,
[n IN nodes(path) | n.name] AS administrativeHierarchy;
The query returns the directly associated administrative unit and its ancestors. The lower bound 0 also allows the original administrative unit to be returned as a path of length zero.
This is useful when asset reports must be aggregated at district, county, regional, or national levels without maintaining a separate query for every administrative tier.
B. Identify downstream assets affected by a power failure
Because the DEPENDS_ON direction runs from the dependent asset to the asset it requires, an outage analysis must traverse the edges in reverse to locate dependent facilities.
MATCH (s:Asset {
assetId: $failedAssetId,
kind: 'Substation'
})
MATCH path =
(dependent:Asset)-[:DEPENDS_ON*1..5]->(s)
RETURN DISTINCT
dependent.assetId AS affectedAssetId,
dependent.name AS affectedAsset,
dependent.kind AS assetType,
length(path) AS dependencyDepth
ORDER BY dependencyDepth;
This query identifies assets whose dependency paths lead to the failed substation. It can discover indirect dependencies as well as direct ones.
The result represents potential dependency impact, not proof that every downstream facility has lost service. Actual outage assessment also needs operating status, backup power, redundancy, capacity, and time-specific state data.
C. Find nearby facilities and inspect their connections
MATCH (a:Asset)
WHERE point.distance(
a.location,
point({
longitude: $longitude,
latitude: $latitude
})
) <= $radiusMeters
RETURN a.assetId AS id,
a.name AS name,
a.kind AS type,
point.distance(
a.location,
point({
longitude: $longitude,
latitude: $latitude
})
) AS distanceMeters
ORDER BY distanceMeters;
Pass parameters such as $longitude, $latitude, and $radiusMeters through the Neo4j driver rather than concatenating user input into query text.
This query combines geographic proximity with a graph-based representation of assets. However, the distance is straight-line geodesic distance, not road-network travel distance. Travel-time or route analysis needs a routable network and an appropriate graph algorithm or external routing engine.
Step 4: Integrate SPARQL endpoints for semantic web GIS
A property graph becomes more useful when it can share meaning with external datasets rather than treating every incoming label as an isolated string.
An RDF dataset might describe an infrastructure asset using a globally identifiable resource, its formal class, its administrative affiliation, and its geometry. GeoSPARQL, an Open Geospatial Consortium standard, provides RDF vocabulary and query extensions for representing and querying geographic information.
For instance, an external dataset could describe a substation as follows:
@prefix ex: <https://data.example.org/id/> .
@prefix schema: <https://schema.org/> .
@prefix geo: <http://www.opengis.net/ont/geosparql#> .
ex:substation-017
a ex:Substation ;
schema:name "East Substation" ;
ex:locatedIn ex:county-001 ;
geo:hasGeometry ex:substation-017-geometry .
ex:substation-017-geometry
geo:asWKT
"POINT(36.85 -1.28)"^^geo:wktLiteral .
The persistent URI provides a bridge between the graph database and the external semantic resource. The WKT literal describes the geographic geometry using the GeoSPARQL vocabulary.
Query semantic relationships with SPARQL
The following query finds substations and the administrative units associated with them:
PREFIX ex: <https://data.example.org/id/>
PREFIX schema: <https://schema.org/>
SELECT ?asset ?name ?region ?regionName
WHERE {
?asset a ex:Substation ;
schema:name ?name ;
ex:locatedIn ?region .
?region schema:name ?regionName .
}
SPARQL matches patterns against RDF triples. This means the query can work across a semantic dataset even when that dataset was created by another agency or maintained independently of Neo4j.
For actual polygon containment, a GeoSPARQL-capable endpoint can evaluate geometries represented with geo:asWKT. For example:
PREFIX ex: <https://data.example.org/id/>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX schema: <https://schema.org/>
SELECT ?asset ?name
WHERE {
?asset a ex:Substation ;
schema:name ?name ;
ex:locatedIn ex:county-001 ;
geo:hasGeometry/geo:asWKT ?assetGeometry .
ex:county-001
geo:hasGeometry/geo:asWKT ?countyGeometry .
FILTER(
geof:sfWithin(?assetGeometry, ?countyGeometry)
)
}
This is a GeoSPARQL query pattern; the endpoint must support the relevant spatial functions, and the dataset must contain valid geometry literals for both resources. The explicit locatedIn relationship provides the semantic association, while sfWithin checks the geometric relationship independently.
Connect RDF and Neo4j
There are two common integration strategies.
Option A: Query a dedicated SPARQL endpoint. Keep authoritative RDF data in a GeoSPARQL-capable triple store. Use SPARQL to retrieve semantic classifications, linked resources, or administrative relationships. Your application can then use canonical identifiers to match those results with nodes in Neo4j, where Cypher handles dependency traversal.
Option B: Import RDF into Neo4j. Neo4j’s Neosemantics (n10s) extension supports importing and exporting RDF, mapping vocabularies, validating graphs with SHACL, and basic inferencing. It is intended for self-hosted Neo4j installations; the project documentation states that the plugin is not available in Neo4j Aura.
For a compatible self-hosted installation, a typical initial configuration is:
CREATE CONSTRAINT n10s_unique_uri IF NOT EXISTS
FOR (r:Resource)
REQUIRE r.uri IS UNIQUE;
CALL n10s.graphconfig.init({
handleVocabUris: 'MAP'
});
Then import a Turtle dataset from a trusted RDF source:
CALL n10s.rdf.import.fetch(
'https://data.example.org/infrastructure.ttl',
'Turtle'
);
Check the Neo4j and extension compatibility requirements before installation. The constraint and graph configuration follow the Neosemantics setup workflow; the RDF import procedure persists triples as mapped graph elements.
An important distinction is that RDF import/export is not the same thing as providing a full GeoSPARQL query engine. If your application requires live SPARQL queries and spatial predicates, retain a compatible RDF endpoint or use an integration layer rather than assuming that importing RDF into Neo4j enables all SPARQL operations inside Cypher.
4. Use Case Scenario: Urban Infrastructure Dependency Mapping

Consider a city authority managing power substations, water-treatment facilities, hospitals, warehouses, and administrative regions.
The authority wants to identify facilities potentially affected by a substation outage and determine which external semantic datasets can enrich the impact assessment.
A combined architecture could work as follows:
-
Load the infrastructure graph. Store asset nodes, geographic points, dependency relationships, and administrative hierarchies in Neo4j.
-
Detect geographic candidates. Use indexed point-distance queries to find nearby assets, then use an appropriate spatial engine to test polygon overlap or containment where required.
-
Trace operational dependencies. Traverse
DEPENDS_ONrelationships to identify downstream facilities and indirect dependencies. -
Enrich the results. Query a SPARQL endpoint for asset classifications, administrative identifiers, infrastructure standards, or publicly linked datasets.
-
Produce a decision-support result. Combine affected asset IDs, dependency paths, locations, criticality, and semantic descriptions for display in a GIS dashboard.
This approach separates three distinct questions: where assets are located, how they depend on one another, and what those assets mean within a shared semantic model.
The architecture can also support supply chain tracking. For example, a warehouse’s location may place it within a flood-prone area, its graph relationships may reveal which hospitals depend on its deliveries, and semantic links may identify the products or service categories those hospitals require. The combined model is more expressive than a map alone because it connects geographic exposure to operational consequences.
5. Engineering Considerations and Performance Optimization
A production-grade graph requires more than importing coordinates and running traversals.
Coordinate consistency: Normalize incoming spatial data to a known coordinate reference system before creating Neo4j points. Do not assume that projected eastings and northings are longitude and latitude. GeoSPARQL WKT literals and Neo4j points must also follow the coordinate-order conventions appropriate to their CRS.
Indexing and query planning: Create uniqueness constraints for stable identifiers and point indexes for frequently filtered locations. Use PROFILE to inspect actual query execution, and filter candidate nodes before exploring large paths.
Relationship direction: Document the meaning of every edge. Reversing DEPENDS_ON can change outage-impact results, even if the same two assets remain connected.
Temporal validity: Administrative boundaries, asset locations, and dependencies change. Model effective dates or versioned relationships where historical analysis matters; an undated graph can silently combine facts from incompatible time periods.
Semantic governance: Preserve external URIs and namespace mappings, validate required properties, and record source provenance. If multiple agencies use different identifiers or definitions for the same real-world feature, explicit entity resolution is needed before linking the records.
Spatial-engine boundaries: Use Neo4j for graph traversal and supported point operations, and use PostGIS or a GeoSPARQL-capable endpoint when full geometry processing is required. A hybrid approach avoids treating a graph database as a replacement for every GIS function.
6. Summary
Geospatial knowledge graphs connect geographic features to operational dependencies, semantic descriptions, and administrative hierarchies. Neo4j and Cypher are particularly effective for traversing connected entities, tracing indirect dependencies, and combining graph relationships with native point-distance queries.
SPARQL provides the interoperability layer for RDF resources and semantic web datasets, while GeoSPARQL adds standardized geographic representation and spatial query capabilities. When these tools are integrated through stable identifiers, explicit mapping rules, and appropriate spatial engines, GIS applications can move beyond isolated feature analysis toward connected, explainable infrastructure and supply chain analysis.
The key architectural principle is to use each technology for its strengths: Neo4j for connected-entity reasoning, SPARQL and RDF for semantic interoperability, and a suitable spatial engine for full geometry operations.