Property Graph
A graph data model where both nodes and relationships can have properties (key-value pairs), commonly used in modern graph databases like Neo4j and TrustGraph.
Core Concepts
A Property Graph is a graph data model where nodes (vertices) and relationships (edges) can have properties stored as key-value pairs, providing a rich, flexible way to model complex data.
Structure
// Property Graph components
{
nodes: [
{
id: "node_1",
labels: ["Person", "Employee"], // Multiple labels
properties: { // Properties on nodes
name: "Jane Smith",
age: 35,
email: "jane@company.com",
skills: ["Python", "ML", "Leadership"]
}
}
],
relationships: [
{
id: "rel_1",
type: "WORKS_AT", // Single type
from: "node_1",
to: "node_2",
properties: { // Properties on relationships
since: "2020-01-15",
role: "Senior Engineer",
department: "AI Research",
salary: 150000
}
}
]
}
Key Features
1. Properties on Everything
// Nodes with properties
CREATE (jane:Person {
name: "Jane Smith",
age: 35,
email: "jane@example.com",
location: "San Francisco"
})
// Relationships with properties
CREATE (jane)-[:WORKS_AT {
since: 2020,
role: "Engineer",
salary: 150000,
remote: true
}]->(company)
2. Multiple Labels
// Nodes can have multiple labels
CREATE (jane:Person:Employee:Engineer {
name: "Jane Smith"
})
// Query by any label
MATCH (n:Engineer) RETURN n
MATCH (n:Employee) RETURN n
MATCH (n:Person:Engineer) RETURN n // Both labels
3. Directed Relationships
// Relationships have direction
(jane)-[:MANAGES]->(team) // Jane manages team
(jane)<-[:REPORTS_TO]-(employee) // Employee reports to Jane
// Can query in either direction
MATCH (jane)-[:MANAGES]->(team)
MATCH (jane)<-[:MANAGES]-(boss)
MATCH (jane)-[:MANAGES]-(connected) // Either direction
vs RDF/Semantic Web
| Feature | Property Graph | RDF Triple Store |
|---|---|---|
| Model | Nodes + Relationships with properties | Subject-Predicate-Object triples |
| Properties | On nodes AND relationships | Only on subjects (nodes) |
| Relationships | First-class, typed edges | Represented as triples |
| Query Language | Cypher, Gremlin | SPARQL |
| Performance | Optimized for traversal | Optimized for inference |
| Flexibility | Very flexible, schema-optional | More rigid, schema-based |
Example Comparison
Property Graph (Cypher):
CREATE (jane:Person {name: "Jane", age: 30})-[:WORKS_AT {since: 2020}]->(acme:Company {name: "Acme"})
RDF (Turtle):
:jane a :Person ;
:name "Jane" ;
:age 30 ;
:worksAt :acme .
:acme a :Company ;
:name "Acme" .
# Relationship properties require reification
:workRelation a :WorksAt ;
:subject :jane ;
:object :acme ;
:since 2020 .
Property graphs are more natural for relationship properties!
Common Use Cases
1. Social Networks
// Rich social connections
(alice:Person)-[:KNOWS {
since: "2015-03-20",
strength: 0.8,
lastContact: "2024-12-15"
}]->(bob:Person)
(alice)-[:LIKES {timestamp: "2024-12-20"}]->(post:Post)
(post)-[:TAGGED]->(topic:Topic {name: "AI"})
2. Recommendation Engines
// Collaborative filtering
MATCH (user:User {id: 123})-[r:RATED]->(movie:Movie)<-[:RATED]-(similar:User)
WHERE r.rating >= 4
MATCH (similar)-[r2:RATED]->(recommendation:Movie)
WHERE r2.rating >= 4 AND NOT (user)-[:RATED]->(recommendation)
RETURN recommendation, count(*) as score
ORDER BY score DESC
3. Fraud Detection
// Suspicious patterns
MATCH (account:Account)-[t:TRANSFERRED {amount}]->(target:Account)
WHERE t.amount > 10000
AND t.timestamp > datetime() - duration('P1D')
AND target.flagged = true
RETURN account, sum(t.amount) as total
Query Examples
Path Finding
// Shortest path
MATCH path = shortestPath((start:Person {name: "Alice"})-[*]-(end:Person {name: "Bob"}))
RETURN path, length(path)
// All paths up to length 4
MATCH path = (start)-[*1..4]-(end)
WHERE start.name = "Alice" AND end.name = "Bob"
RETURN path
Aggregations
// Count relationships
MATCH (company:Company)-[:EMPLOYS]->(employee:Person)
RETURN company.name, count(employee) as headcount
ORDER BY headcount DESC
// Aggregate properties
MATCH (dept:Department)-[:HAS_EMPLOYEE]->(emp:Person)
RETURN dept.name, avg(emp.salary) as avg_salary, max(emp.salary) as max_salary
TrustGraph Implementation
// TrustGraph uses property graph model
await trustgraph.graph.createNode({
labels: ["Person", "Employee"],
properties: {
name: "Jane Smith",
department: "Engineering",
skills: ["Python", "Go", "Kubernetes"]
}
});
await trustgraph.graph.createRelationship({
type: "WORKS_ON",
from: "person_jane",
to: "project_x",
properties: {
role: "Lead Developer",
allocation: 0.8, // 80% time
since: "2024-01-01"
}
});
// Query with Cypher
const results = await trustgraph.query({
cypher: `
MATCH (p:Person)-[r:WORKS_ON]->(proj:Project)
WHERE r.allocation > 0.5
RETURN p.name, proj.name, r.role
`
});
See Also
Examples
- •A Person node with properties {name: 'John', age: 30} connected via WORKS_AT relationship with properties {since: 2020, role: 'Engineer'}
- •Storing metadata like confidence scores, timestamps, and sources on both entities and relationships