Combined Multi-Model Examples¶
Demonstrates how Relational, NoSQL, RDF, and LPG models work together in IndentiaDB. Each example shows cross-model transactions and unified queries across all four data models in a single instance.
Table of Contents¶
- Relational / SQL Style
- NoSQL / Document
- Graph RDF (Triples)
- Graph LPG (Property Graph)
- Combined: Document + RDF + LPG in One Transaction
1. Relational / SQL Style¶
Standard typed tables with fields, aggregates, subqueries, and updates.
-- Schema: typed tables
DEFINE TABLE employee SCHEMAFULL;
DEFINE FIELD name ON employee TYPE string;
DEFINE FIELD department ON employee TYPE string;
DEFINE FIELD salary ON employee TYPE number;
DEFINE FIELD hire_date ON employee TYPE string;
DEFINE TABLE department SCHEMAFULL;
DEFINE FIELD name ON department TYPE string;
DEFINE FIELD budget ON department TYPE number;
DEFINE FIELD location ON department TYPE string;
-- Data
CREATE department:engineering CONTENT {
name: "Engineering", budget: 500000, location: "Amsterdam"
};
CREATE department:research CONTENT {
name: "Research", budget: 300000, location: "Utrecht"
};
CREATE employee:alice CONTENT {
name: "Alice van den Berg", department: "Engineering",
salary: 85000, hire_date: "2023-03-15"
};
CREATE employee:bob CONTENT {
name: "Bob de Vries", department: "Engineering",
salary: 92000, hire_date: "2022-01-10"
};
CREATE employee:carol CONTENT {
name: "Carol Jansen", department: "Research",
salary: 78000, hire_date: "2024-06-01"
};
-- Queries
SELECT name, salary FROM employee WHERE salary > 80000 ORDER BY salary DESC;
-- Bob (92000), Alice (85000)
SELECT department, math::mean(salary) AS avg_salary FROM employee GROUP BY department;
-- Subquery: employees in departments with budget > 400k
SELECT name, department FROM employee
WHERE department IN (SELECT VALUE name FROM department WHERE budget > 400000);
-- Alice and Bob (Engineering)
UPDATE employee:alice SET salary = 90000;
2. NoSQL / Document¶
Schemaless tables with nested objects, arrays, and record links.
DEFINE TABLE project SCHEMALESS;
DEFINE TABLE task SCHEMALESS;
CREATE project:indentiagraph CONTENT {
name: "IndentiaGraph",
status: "active",
tags: ["database", "graph", "rdf", "lpg"],
metadata: {
created: "2024-01-15",
lead: "Alice",
priority: "high"
},
milestones: [
{ name: "v1.0", date: "2025-06-01", completed: true },
{ name: "v2.0", date: "2026-03-01", completed: false }
]
};
CREATE task:lpg_csr CONTENT {
title: "Implement CSR adjacency",
project: project:indentiagraph,
assignee: "Bob", status: "done",
labels: ["performance", "lpg"]
};
CREATE task:lpg_pagerank CONTENT {
title: "Add PageRank algorithm",
project: project:indentiagraph,
assignee: "Bob", status: "done",
labels: ["algorithm", "lpg"],
depends_on: [task:lpg_csr]
};
CREATE task:acl_integration CONTENT {
title: "ACL integration for LPG",
project: project:indentiagraph,
assignee: "Carol", status: "in_progress",
labels: ["security", "lpg"]
};
-- Nested field access
SELECT name, metadata.lead FROM project WHERE status = "active";
-- "IndentiaGraph", lead: "Alice"
-- Array contains
SELECT title, assignee FROM task WHERE labels CONTAINS "lpg";
-- 3 tasks
-- Nested array filter
SELECT milestones[WHERE completed = true] AS done FROM project:indentiagraph;
-- [{name: "v1.0", ...}]
-- Record link traversal
SELECT title, project.name AS project_name FROM task WHERE assignee = "Bob";
-- Both of Bob's tasks show project_name: "IndentiaGraph"
3. Graph RDF¶
RDF triples stored in the triples table with subject/predicate/object structure.
-- Ontology: Person class
CREATE triples CONTENT {
subject: { "_rdf_type": "NamedNode", "iri": "http://example.org/Person" },
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
object: { "_rdf_type": "NamedNode", "iri": "http://www.w3.org/2002/07/owl#Class" },
graph: "default"
};
-- Instances with properties and relationships
CREATE triples CONTENT {
subject: { "_rdf_type": "NamedNode", "iri": "http://example.org/alice" },
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
object: { "_rdf_type": "NamedNode", "iri": "http://example.org/Person" },
graph: "default"
};
CREATE triples CONTENT {
subject: { "_rdf_type": "NamedNode", "iri": "http://example.org/alice" },
predicate: "http://xmlns.com/foaf/0.1/name",
object: { "_rdf_type": "Literal", "value": "Alice van den Berg",
"datatype": "http://www.w3.org/2001/XMLSchema#string" },
graph: "default"
};
CREATE triples CONTENT {
subject: { "_rdf_type": "NamedNode", "iri": "http://example.org/alice" },
predicate: "http://xmlns.com/foaf/0.1/knows",
object: { "_rdf_type": "NamedNode", "iri": "http://example.org/bob" },
graph: "default"
};
-- (Similar triples for bob and carol...)
-- Query: find all Person instances
SELECT subject.iri AS person FROM triples
WHERE predicate = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
AND object.iri = "http://example.org/Person";
-- Query: who does Alice know?
SELECT object.iri AS friend FROM triples
WHERE subject.iri = "http://example.org/alice"
AND predicate = "http://xmlns.com/foaf/0.1/knows";
-- "http://example.org/bob"
-- Query: get Alice's name
SELECT object.value AS name FROM triples
WHERE subject.iri = "http://example.org/alice"
AND predicate = "http://xmlns.com/foaf/0.1/name";
-- "Alice van den Berg"
4. Graph LPG¶
Project RDF triples into an LPG for traversals, shortest path, PageRank, and connected components.
RDF data: alice knows bob, bob knows carol (all Person-typed).
LPG Traverse (1-hop from Alice):
{
"kind": {
"Traverse": {
"start": { "iri": "http://example.org/alice" },
"edge": "knows",
"direction": "Out",
"min_hops": 1, "max_hops": 1,
"target_label": "Person"
}
},
"limit": 10,
"return_fields": ["id", "hop_count"]
}
Result: bob (1 hop)
LPG Traverse (2-hop, friends-of-friends):
Same query with max_hops: 2.
Result: bob (1 hop), carol (2 hops)
Shortest Path (Alice to Carol):
{
"kind": {
"ShortestPath": {
"start": { "iri": "http://example.org/alice" },
"target": { "iri": "http://example.org/carol" },
"edge": "knows",
"direction": "Out"
}
}
}
Result: length = 2
PageRank: Scores sum to ~1.0. All connected Person nodes contribute.
Connected Components: All Person nodes (alice, bob, carol) are in one component.
5. Combined: Document + RDF + LPG in One Transaction¶
This is the key multi-model pattern. A single transaction spans:
- RDF triples for semantic types (alice/bob are Person)
- Document table (
hr_employee) for business data (salary, department) - LPG projection that merges both sources into a unified graph
Setup¶
-- RDF: alice and bob are Person instances
CREATE triples CONTENT {
subject: { "_rdf_type": "NamedNode", "iri": "http://example.org/alice" },
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
object: { "_rdf_type": "NamedNode", "iri": "http://example.org/Person" },
graph: "default"
};
CREATE triples CONTENT {
subject: { "_rdf_type": "NamedNode", "iri": "http://example.org/bob" },
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
object: { "_rdf_type": "NamedNode", "iri": "http://example.org/Person" },
graph: "default"
};
-- Document: HR employee data with RDF IRI linkage
DEFINE TABLE hr_employee SCHEMALESS;
CREATE hr_employee:alice CONTENT {
name: "Alice van den Berg",
rdf_iri: "http://example.org/alice",
department: "Engineering",
salary: 85000,
colleague_iri: "http://example.org/bob"
};
CREATE hr_employee:bob CONTENT {
name: "Bob de Vries",
rdf_iri: "http://example.org/bob",
department: "Engineering",
salary: 92000
};
LPG Projection Config¶
{
"document_rules": [{
"table": "hr_employee",
"label": "Employee",
"iri_field": "rdf_iri",
"include_fields": ["name", "department", "salary", "rdf_iri"],
"edge_fields": [{
"field": "colleague_iri",
"edge_type": "colleague"
}]
}]
}
Result After Projection¶
Alice's LPG node has:
- Labels:
["Person", "Employee"](Person from RDF, Employee from document rule) - Properties:
{department: "Engineering", salary: 85000, name: "Alice van den Berg"} - Edges:
colleague -> bob
Traverse Colleague Edges¶
{
"kind": {
"Traverse": {
"start": { "iri": "http://example.org/alice" },
"edge": "colleague",
"direction": "Out",
"min_hops": 1, "max_hops": 1,
"target_label": "Employee"
}
},
"limit": 10,
"return_fields": ["id", "name", "department"]
}
Result: {id: "http://example.org/bob", name: "Bob de Vries", department: "Engineering"}
Incremental RDF Delta¶
Add a new RDF type for Alice without rebuilding:
Result: Alice now has labels ["Person", "Employee", "Manager"]. Document properties are preserved.
Incremental Document Delta¶
Update Bob's salary:
Result: Bob's salary property in the LPG updates to 105000. All other labels and properties are preserved.
Final Graph Analysis¶
After both deltas:
- PageRank: Computed across the combined graph (RDF edges + document edges)
- Connected Components (Employee filter): Alice and Bob are in one component (connected via colleague edge)
Key Takeaway¶
The multi-model architecture means you do not need to choose between a graph database, a document store, an RDF triple store, and a relational database. IndentiaDB unifies all four models:
| Model | Use For |
|---|---|
| Relational / SQL | Structured data with typed schemas, aggregates, and joins |
| NoSQL / Document | Flexible, heterogeneous records with nested fields and arrays |
| RDF Triple Store | Semantic knowledge representation, ontologies, SPARQL queries |
| LPG | Graph algorithms (PageRank, shortest path, connected components) over combined data |
All models share the same storage engine, the same transaction system, and the same security layer.