Example SPARQL Queries
This document provides example SPARQL queries for common use cases with the Record Harm Ontology.
Setup
from rdflib import Graph
g = Graph()
g.parse("ontology/record-harm-ontology.ttl", format="turtle")
g.parse("examples/example-harm-events.ttl", format="turtle")
Basic Queries
List All Prime Harms
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label WHERE {
?harm a ex:PrimeHarm ;
rdfs:label ?label .
}
ORDER BY ?label
List All Composite Harms with Dependencies
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?composite ?label ?dependency ?depLabel WHERE {
?composite a ex:CompositeHarm ;
rdfs:label ?label ;
ex:buildsUpon ?dependency .
?dependency rdfs:label ?depLabel .
}
ORDER BY ?label ?depLabel
Find Harms Targeting Specific Aspect
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?harm ?label ?definition WHERE {
?harm ex:targetsAspect ex:Authenticity ;
rdfs:label ?label ;
skos:definition ?definition .
}
Dependency Analysis
Find All Transitive Dependencies
v3.0: the dependency graph is currently flat — every composite builds directly on primes, maximum chain depth 1 — so
ex:buildsUpon+returns the same rows asex:buildsUponhere. The two-hop chain that used to exist (Obfuscation → Suppression → Omission) was the defect fixed in v3.0. The+form is kept because it remains correct if a composite is ever given a composite dependency.
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?composite ?label ?prime ?primeLabel WHERE {
?composite a ex:CompositeHarm ;
rdfs:label ?label ;
ex:buildsUpon+ ?prime .
?prime a ex:PrimeHarm ;
rdfs:label ?primeLabel .
}
ORDER BY ?label ?primeLabel
Find Harms That Build Upon Omission
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label WHERE {
?harm ex:buildsUpon ex:Omission ;
rdfs:label ?label .
}
Count Underlying Prime Harms
Counts the distinct prime harms in each composite's transitive closure (how many primes it ultimately rests on) — not path depth / longest chain, which would need a recursive longest-path query.
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label (COUNT(DISTINCT ?prime) as ?primeCount) WHERE {
?harm a ex:CompositeHarm ;
rdfs:label ?label ;
ex:buildsUpon+ ?prime .
?prime a ex:PrimeHarm .
}
GROUP BY ?harm ?label
ORDER BY DESC(?primeCount)
Record Location (bearer and nesting)
New in v3.1. Where a record lives is stated with ex:bearer, and what it is
made of with ex:hasElement. Neither needed a new harm type — the
inside-agent / inside-community distinction is a property of the record, not a
dimension of harm.
Inside-agent vs inside-community records
A record borne by exactly one agent resides inside that agent; one borne by several, or by a collective agent, resides in a community.
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?record ?label (COUNT(DISTINCT ?bearer) as ?bearers) WHERE {
?record a ex:Record ;
rdfs:label ?label ;
ex:bearer ?bearer .
}
GROUP BY ?record ?label
ORDER BY ?bearers
Bearer count alone cannot tell a single individual bearer from a single collective one — a parish register borne by the parish returns
1, same as a private memory. That is deliberate: per the note onex:Agent, the individual/collective distinction is left to an external vocabulary, so add?bearer a foaf:Group(orprov:Organization) to split them.
Self-directed harm (repression, self-deception)
The perpetrator of the event is also the bearer of the record it harms.
Inexpressible before ex:bearer existed.
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?event ?eventLabel ?harmType ?agent WHERE {
?event a ex:HarmEvent ;
ex:perpetrator ?agent ;
ex:harms ?record ;
ex:ofType ?harmType .
?record ex:bearer ?agent .
OPTIONAL { ?event rdfs:label ?eventLabel }
}
Records nested inside a community register
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?whole ?wholeLabel ?element ?elementLabel WHERE {
?whole ex:hasElement+ ?element .
OPTIONAL { ?whole rdfs:label ?wholeLabel }
OPTIONAL { ?element rdfs:label ?elementLabel }
}
ex:hasElementis asymmetric and irreflexive but not transitive (the v2.3 precedent — transitivity would make it non-simple in OWL 2 DL and forbid those two guards), so nesting is walked with+exactly asex:buildsUponis. A nesting cycle deeper than two steps violates no declared OWL axiom and is caught instead byex:RecordAcyclicShapein the shapes file.
Agent-to-community boundary: what a register leaves out
Records held by some agent that are not elements of a given register. Candidate
ex:Omission from that register — the modeled form of refusing a record entry.
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?record ?label ?bearer WHERE {
?record a ex:Record ;
ex:bearer ?bearer .
OPTIONAL { ?record rdfs:label ?label }
FILTER NOT EXISTS { ex:ParishRegister ex:hasElement+ ?record }
FILTER (?record != ex:ParishRegister)
}
This finds candidates, not harms. Most records a community does not hold were never owed to it; omission is a harm only where the record should have been part of the register, and nothing in this ontology supplies the "should" (see the scope boundary note at
ex:RecordHarm).
Event Queries
List All Harm Events
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dc: <http://purl.org/dc/terms/>
SELECT ?event ?label ?type ?date ?severity WHERE {
?event a ex:HarmEvent ;
rdfs:label ?label ;
ex:ofType ?harmType ;
dc:date ?date .
?harmType rdfs:label ?type .
OPTIONAL { ?event ex:severity ?severity }
}
ORDER BY DESC(?date)
Find High-Severity Events
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?event ?label ?severity ?record WHERE {
?event a ex:HarmEvent ;
rdfs:label ?label ;
ex:severity ?severity ;
ex:harms ?record .
FILTER(?severity >= 8)
}
ORDER BY DESC(?severity)
Events by Perpetrator
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?perpetrator ?perpLabel (COUNT(?event) as ?eventCount) WHERE {
?event a ex:HarmEvent ;
ex:perpetrator ?perpetrator .
?perpetrator rdfs:label ?perpLabel .
}
GROUP BY ?perpetrator ?perpLabel
ORDER BY DESC(?eventCount)
Timeline of Events Against Specific Record
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dc: <http://purl.org/dc/terms/>
SELECT ?event ?label ?type ?date ?severity WHERE {
?event a ex:HarmEvent ;
rdfs:label ?label ;
ex:harms ex:AuditLog2026Q2 ;
ex:ofType ?harmType ;
dc:date ?date .
?harmType rdfs:label ?type .
OPTIONAL { ?event ex:severity ?severity }
}
ORDER BY ?date
Pattern Analysis
Identify Potential Cover-up Patterns
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?record ?recordLabel
(COUNT(DISTINCT ?suppressionEvent) as ?suppressions)
(COUNT(DISTINCT ?alterationEvent) as ?alterations)
(COUNT(DISTINCT ?denialEvent) as ?denials)
WHERE {
?record a ex:Record ;
rdfs:label ?recordLabel .
OPTIONAL {
?suppressionEvent ex:ofType ex:Suppression ;
ex:harms ?record .
}
OPTIONAL {
?alterationEvent ex:ofType ex:Alteration ;
ex:harms ?record .
}
OPTIONAL {
?denialEvent ex:ofType ex:Denial ;
ex:harms ?record .
}
}
GROUP BY ?record ?recordLabel
HAVING (?suppressions > 0 && ?alterations > 0 && ?denials > 0)
Aspect Analysis
Aspect Attack Surface
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?aspect ?aspectLabel (COUNT(DISTINCT ?harm) as ?harmCount) WHERE {
?harm ex:targetsAspect ?aspect .
?aspect skos:prefLabel ?aspectLabel .
}
GROUP BY ?aspect ?aspectLabel
ORDER BY DESC(?harmCount)
Aspect Coverage by Prime
The diagnostic that found the v3.0 defect. Every aspect should appear with at
least one prime; an aspect whose primes column is empty means some composite
is rooted in a prime that does not actually attack that aspect — before v3.0
ex:Accessibility came back empty, because ex:Suppression was a composite
hanging off ex:Omission on an edge that contradicted both definitions.
scripts/validate.py runs this as a hard check (check_aspect_coverage); it
is reproduced here because the grouped form is the one worth eyeballing when
adding a harm or an aspect.
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?aspectLabel
(GROUP_CONCAT(DISTINCT ?primeLabel; separator=", ") AS ?primes)
WHERE {
?aspect skos:inScheme ex:RecordAspectScheme ;
skos:prefLabel ?aspectLabel .
OPTIONAL {
?prime a ex:PrimeHarm ;
ex:targetsAspect ?aspect ;
rdfs:label ?primeLabel .
}
}
GROUP BY ?aspectLabel
ORDER BY ?aspectLabel
OPTIONALis load-bearing here: the point of the query is the aspects with no prime, and an inner join would silently drop exactly those rows. Note also that rdflib raisesNotBoundErroronGROUP_CONCAT(DISTINCT ...)over a variable left unbound byOPTIONAL, so with rdflib useCOALESCE(?primeLabel, "NONE")inside the concat, or do the grouping in Python ascheck_aspect_coveragedoes.
Multi-Aspect Harms
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label (COUNT(?aspect) as ?aspectCount) WHERE {
?harm a ex:RecordHarm ;
rdfs:label ?label ;
ex:targetsAspect ?aspect .
}
GROUP BY ?harm ?label
HAVING (?aspectCount > 1)
ORDER BY DESC(?aspectCount)
Detectability and Reversibility
Difficult to Detect Harms
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label WHERE {
?harm a ex:RecordHarm ;
rdfs:label ?label ;
ex:detectability ex:DifficultToDetect .
}
Irreversible Harms
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label WHERE {
?harm a ex:RecordHarm ;
rdfs:label ?label ;
ex:reversibility ex:Irreversible .
}
Risk Matrix (Detectability × Reversibility)
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?harm ?label ?detectLabel ?reverseLabel WHERE {
?harm a ex:RecordHarm ;
rdfs:label ?label ;
ex:detectability ?detect ;
ex:reversibility ?reverse .
?detect skos:prefLabel ?detectLabel .
?reverse skos:prefLabel ?reverseLabel .
}
ORDER BY ?detectLabel ?reverseLabel
Validation Queries
Find Unclassified Harms
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label WHERE {
?harm a ex:RecordHarm ;
rdfs:label ?label .
FILTER NOT EXISTS { ?harm a ex:PrimeHarm }
FILTER NOT EXISTS { ?harm a ex:CompositeHarm }
}
Find Composites Without Dependencies
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label WHERE {
?harm a ex:CompositeHarm ;
rdfs:label ?label .
FILTER NOT EXISTS { ?harm ex:buildsUpon ?dep }
}
Find Harms Without Aspect Targeting
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?harm ?label WHERE {
?harm a ex:RecordHarm ;
rdfs:label ?label .
FILTER NOT EXISTS { ?harm ex:targetsAspect ?aspect }
}
Advanced Queries
Harm Propagation Analysis
Find all harms that could cascade from a prime harm:
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?prime ?primeLabel ?composite ?compositeLabel WHERE {
?prime a ex:PrimeHarm ;
rdfs:label ?primeLabel .
?composite ex:buildsUpon+ ?prime ;
rdfs:label ?compositeLabel .
}
ORDER BY ?primeLabel ?compositeLabel
Event Clustering by Time Window
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?record (COUNT(?event) as ?eventCount) WHERE {
?event a ex:HarmEvent ;
ex:harms ?record ;
dc:date ?date .
FILTER(?date >= "2026-05-01"^^xsd:date &&
?date <= "2026-05-31"^^xsd:date)
}
GROUP BY ?record
HAVING (?eventCount > 1)
Severity Distribution
PREFIX ex: <https://www.epistemic-ontology.net/record-harm#>
SELECT ?severity (COUNT(?event) as ?count) WHERE {
?event a ex:HarmEvent ;
ex:severity ?severity .
}
GROUP BY ?severity
ORDER BY ?severity