The question is not whether graphs help. It is what the graph model makes native.
Irina Adamchic’s article demonstrates a layered Neo4j knowledge graph for real-estate management. This edition holds that business case constant and rebuilds it as RDF, so the distinction is inspectable in data rather than asserted in prose.
Source implementation · Neo4j
- Fixed Entity Architecture
- Linked Property Graph layers
- Cypher and vector-index prefilter
- APOC, MCP, Graph Builder, local and hosted models
Proof-of-concept edition · Virtuoso/RDF
- IRI-identified entities and ontology terms
- RDF/OWL semantics and SHACL-style constraints
- Pure SPARQL over layers, evidence, rules, and findings
- Portable Turtle companion graph
The same five layers, expressed as linked RDF resources
The POC preserves the article’s OntologyLayer, LegalLayer, ContractsLayer, InvoiceLayer, and RulesLayer. Stable IRIs connect a heat pump, installation record, warranty, service contract, invoice, legal requirement, rules, and findings across those layers.
Neo4j and Virtuoso solve the graph problem at different abstraction levels
This is not a generic “semantic layer” bolted onto Neo4j. It is a concrete comparison between the source’s Neo4j property-graph design and a Virtuoso RDF implementation of the same evidence and decisions.
| Dimension | Neo4j in the source | Virtuoso RDF POC |
|---|---|---|
| Graph model | Labeled property graph with projected ontology entities | RDF quad store with native IRIs, triples, named graphs, and ontology terms |
| Identity | Application-controlled node identity | Web-scale HTTP IRIs shared across graphs and systems |
| Schema | Fixed Entity Architecture, labels, and properties | RDF/OWL classes and properties with domains, ranges, hierarchy, and alignment |
| Layers | Labels and relationships partition the LPG | Named resources and graph membership preserve layers without duplicating identity |
| Query | Cypher | SPARQL 1.1 plus Virtuoso extensions where explicitly used |
| GraphRAG | Vector index returns top-k OntologyLayer nodes | Pure SPARQL graph patterns retrieve ontology instances, evidence paths, and validation findings |
| Validation | Application queries and procedural checks | ASK queries, SHACL-style constraints, inference, and named validation findings |
| Provenance | Modeled as graph properties when designed in | PROV-O and named graph identifiers are first-class RDF |
| Interchange | Mapping/export step required for RDF ecosystems | Native RDF serializations and Linked Data access |
| This POC | Source architecture and Cypher preserved for fair comparison | 1,215 triples; six ASK proofs; eight named findings; pure SPARQL workbench |
An invoice verdict with a traversable evidence path
The illustrative invoice is arithmetically correct and matches the property, asset, supplier, and tax evidence. It nevertheless fails the covered-service rule: a €120 diagnostic visit was billed despite the service contract covering one diagnostic visit.
Invoice RE-2026-0017
| Diagnostic visit | €120.00 |
| Filter replacement | €180.00 |
| Technician travel | €100.00 |
| Tax | €76.00 |
| Total | €476.00 |
Asset: HP-DE-2048 · Supplier: ThermoHaus Service · Call-out ceiling: €450.00
Validation outcome
Result set: 5 pass · 2 warning · 1 fail. Each finding is a named RDF resource linked to its rule and evidence.
Invoice validation as portable RDF/SPARQL
The proof follows the generated ontology instances directly: layer membership, invoice details, validation findings, and the covered-service failure path. The queries avoid text-search and vector-function extensions, so the distinction from the source Neo4j vector prefilter is visible in the data and query patterns.
Ontology slice pure SPARQL
Retrieves the ontology concepts required for the heat-pump invoice scenario from the RDF graph.
Show ontology-slice SPARQL
PREFIX schema: <http://schema.org/>
PREFIX : <https://www.linkedin.com/pulse/power-layered-knowledge-graphs-applied-real-estate-adamchic-phd-vv4df/#>
SELECT ?term ?name ?sourceOntology
FROM <https://linkeddata.uriburner.com/DAV/demos/daas/power-layered-knowledge-graphs-real-estate-neo4j-virtuoso-gpt5-chat-1.ttl>
WHERE {
?term :inLayer :ontologyLayer ;
schema:name ?name .
OPTIONAL { ?sourceOntology schema:hasPart ?term }
VALUES ?term { :heatPumpConcept :invoiceConcept :serviceContractConcept :warrantyConcept :legalRequirementConcept }
}
ORDER BY ?nameEvidence path pure SPARQL
Follows the failed covered-service path from validation finding to invoice, diagnostic line, service contract, and rule.
Show covered-service path SPARQL
PREFIX schema: <http://schema.org/>
PREFIX : <https://www.linkedin.com/pulse/power-layered-knowledge-graphs-applied-real-estate-adamchic-phd-vv4df/#>
SELECT ?finding ?invoice ?lineItem ?lineName ?lineAmount ?serviceContract ?contractText ?rule
FROM <https://linkeddata.uriburner.com/DAV/demos/daas/power-layered-knowledge-graphs-real-estate-neo4j-virtuoso-gpt5-chat-1.ttl>
WHERE {
?finding :evaluatesRule :ruleCoveredDiagnostic ;
:focusNode ?invoice ;
:hasEvidence ?lineItem, ?serviceContract ;
:evaluatesRule ?rule .
?invoice a schema:Invoice ;
schema:hasPart ?lineItem .
?lineItem a :InvoiceLineItem ;
schema:name ?lineName ;
:observedAmount ?lineAmount .
?serviceContract schema:about :heatPumpHPDE2048 ;
schema:description ?contractText .
FILTER(?lineAmount > 0)
}
ORDER BY ?finding ?lineItemWorkbench query set
The SPARQL Workbench exposes recipes for layer inventory, invoice instance details, validation findings, covered-service evidence, ontology-slice retrieval, and graph sampling.
Show the source Cypher vector prefilter
CALL db.index.vector.queryNodes($index_name, $k, $embedding)
YIELD node AS vectorNode, score AS vectorScore
WITH vectorNode, vectorScore
WHERE vectorNode:OntologyLayer AND vectorNode.name IS NOT NULL
RETURN vectorNode.name AS name,
coalesce(vectorNode.uri, '') AS uri,
coalesce(vectorNode.kind, 'class') AS kind,
coalesce(vectorNode.ontologies, []) AS ontologies,
vectorScore AS score
ORDER BY vectorScore DESC