Two Graph Data Models
There are two dominant graph data models in use today:
- RDF (Resource Description Framework) — the W3C standard, used by semantic web and linked data
- Property Graph (LPG — Labeled Property Graph) — used by Neo4j, TinkerPop, Amazon Neptune
Both represent data as nodes and edges, but they differ in important ways.
Nodes
- AlicePerson
Node label: Person
- BobPerson
Node label: Person
- Acme CorpCompany
Node label: Company
- LondonCity
Node label: City
Edges
- aliceKNOWSbob
- aliceWORKS_ATacme
- bobWORKS_ATacme
- acmeHQ_INlondon
Comparison: Property Graph vs RDF
| Feature | Property Graph (LPG) | RDF |
|---|---|---|
| Edge properties | Yes — edges have key-value properties | No — must use reification |
| Blank nodes | No | Yes |
| Query language | Cypher (Neo4j), Gremlin (TinkerPop) | SPARQL |
| Standards body | Vendor-driven (Neo4j) | W3C standard |
| Interoperability | Limited | High (Linked Data) |
| Reasoning/inference | Limited (plugins) | Built-in (OWL/RDFS reasoners) |
| Schema | Optional labels and constraints | RDFS/OWL ontologies |
| Best for | Operational graph apps, recommendations, fraud | Linked data, semantic web, knowledge management |
Cypher: Neo4j's Query Language
Cypher uses an ASCII-art-inspired syntax where nodes are () and edges are --> or -[]->:
// Create nodes and relationships
CREATE (alice:Person {name: 'Alice', age: 32})
CREATE (bob:Person {name: 'Bob', age: 28})
CREATE (acme:Company {name: 'Acme Corp', founded: 2005})
CREATE (alice)-[:KNOWS {since: '2020'}]->(bob)
CREATE (alice)-[:WORKS_AT {role: 'Engineer', since: '2019'}]->(acme)
CREATE (bob)-[:WORKS_AT {role: 'Data Scientist', since: '2021'}]->(acme)
// Find all people who work at Acme Corp
MATCH (p:Person)-[r:WORKS_AT]->(c:Company {name: 'Acme Corp'})
RETURN p.name, r.role, r.since
// Find colleagues (people working at the same company)
MATCH (a:Person)-[:WORKS_AT]->(c:Company)<-[:WORKS_AT]-(b:Person)
WHERE a.name = 'Alice' AND a <> b
RETURN b.name, c.name
// Find friends-of-friends
MATCH (alice:Person {name: 'Alice'})-[:KNOWS*2]->(fof:Person)
WHERE NOT (alice)-[:KNOWS]->(fof)
RETURN DISTINCT fof.nameEdge Properties in Detail
One of the biggest practical differences is edge properties. In Neo4j, you can attach metadata to a relationship:
(alice)-[:WORKS_AT {role: 'Engineer', since: '2019', salary: 95000}]->(acme)
In RDF, you can't attach properties to a triple. To model this, you need RDF Reification — creating a new node to represent the relationship:
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ex: <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
# Direct triple (no metadata)
ex:alice ex:worksAt ex:acme .
# Reified statement — to add metadata to the above triple
ex:statement1
a rdf:Statement ;
rdf:subject ex:alice ;
rdf:predicate ex:worksAt ;
rdf:object ex:acme ;
ex:role "Engineer" ;
ex:since "2019-01-01"^^xsd:date .
# RDF* (RDF-star) — a newer, cleaner approach
# (supported by Apache Jena 4.x, Stardog, GraphDB)
<<ex:alice ex:worksAt ex:acme>>
ex:role "Engineer" ;
ex:since "2019-01-01"^^xsd:date .Summary
In this chapter you learned:
- Property Graph (LPG) allows edges to have properties; used by Neo4j with the Cypher query language
- RDF uses URIs for edges (no edge properties); queried with SPARQL; better for interoperability
- Edge properties in RDF require reification (or the newer RDF-star standard)
- Choose based on your needs: operational apps → LPG; linked data/reasoning → RDF
Next, we'll learn how to build a knowledge graph from raw data using practical tools and code.