Copy and paste these queries into the Neo4j Aura Query interface to explore the Aircraft Digital Twin graph.
| Concept | What It Does |
|---|---|
MATCH (n:Label) |
Find nodes by label — the starting point for most queries |
(a)-[:REL]->(b) |
Traverse a relationship between two nodes (direction matters) |
{key: 'value'} |
Inline property filter — shorthand for WHERE n.key = 'value' |
WHERE |
Filter results by condition after a MATCH |
OPTIONAL MATCH |
Like a SQL LEFT JOIN — keeps the row even if the pattern has no match |
RETURN ... AS alias |
Project properties and rename columns |
count(), avg(), sum(), min(), max() |
Aggregate functions — work like their SQL equivalents |
collect() |
Aggregate values into a list (one row per group) |
DISTINCT |
De-duplicate values, usable inside collect(DISTINCT x) |
ORDER BY ... DESC |
Sort results (ascending by default) |
LIMIT n |
Cap the number of returned rows |
WITH |
Pipe results from one query part to the next — like a SQL CTE |
CASE WHEN ... THEN ... ELSE ... END |
Conditional expression for computed columns |
EXISTS { } |
Existential subquery — checks whether a pattern exists without returning it |
CALL db.schema.visualization() |
Built-in procedure that returns the graph's node labels, relationship types, and properties |
| Multi-hop patterns | Chain relationships in a single MATCH to traverse several hops at once, e.g. (a)-[:R1]->(b)-[:R2]->(c) |
CALL db.schema.visualization()Concepts:
CALLinvokes a built-in procedure. This one introspects the database and returns every node label, relationship type, and how they connect — useful for orienting yourself in an unfamiliar graph.
MATCH (n)
RETURN labels(n)[0] AS Label, count(n) AS Count
ORDER BY Count DESCConcepts:
labels(n)returns a list of labels on a node.[0]takes the first one. This gives a quick census of your entire graph.
MATCH (a:Aircraft {tail_number: 'N95040A'})-[r1:HAS_SYSTEM]->(s:System)-[r2:HAS_COMPONENT]->(c:Component)
RETURN a, r1, s, r2, cConcepts: multi-hop pattern, inline property filter, returning full nodes and relationships (renders as a graph visualization in Neo4j Browser).
MATCH (a:Aircraft {tail_number: 'N95040A'})-[:HAS_SYSTEM]->(s:System)
WHERE s.type IS NOT NULL AND s.name IS NOT NULL
OPTIONAL MATCH (s)-[:HAS_COMPONENT]->(c:Component)
RETURN a.tail_number AS Aircraft,
a.model AS Model,
s.name AS System,
s.type AS SystemType,
collect(c.name) AS Components
ORDER BY s.type, s.nameConcepts:
OPTIONAL MATCHkeeps systems that have no components,collect()groups component names into a list per system,WHERE ... IS NOT NULLfilters out incomplete data.
MATCH (a:Aircraft)
RETURN a.operator AS Operator, count(a) AS CountConcepts:
count()aggregation with implicit grouping — non-aggregated columns (Operator) become the group key, just like SQLGROUP BY.
MATCH (a:Aircraft)
RETURN a.manufacturer AS Manufacturer,
count(a) AS AircraftCount,
collect(DISTINCT a.model) AS Models
ORDER BY AircraftCount DESCConcepts:
collect(DISTINCT ...)builds a de-duplicated list of models per manufacturer.
MATCH (a:Aircraft {tail_number: 'N95040A'})
OPTIONAL MATCH (a)-[:HAS_SYSTEM]->(s:System)
OPTIONAL MATCH (a)-[:OPERATES_FLIGHT]->(f:Flight)
OPTIONAL MATCH (a)-[:HAS_REMOVAL]->(r:Removal)
RETURN a.tail_number AS TailNumber,
a.model AS Model,
a.manufacturer AS Manufacturer,
a.operator AS Operator,
count(DISTINCT s) AS Systems,
count(DISTINCT f) AS Flights,
count(DISTINCT r) AS RemovalsConcepts: multiple
OPTIONAL MATCHclauses gather counts from different relationship types.count(DISTINCT ...)prevents double-counting caused by the cross-product of multiple patterns.
MATCH (c:Component)
RETURN c.type AS ComponentType, count(c) AS Count
ORDER BY Count DESCConcepts: simple label scan with aggregation — counts how many components exist of each type.
MATCH (s:System {type: 'Engine'})-[:HAS_COMPONENT]->(c:Component)
RETURN c.type AS ComponentType, count(c) AS Count
ORDER BY Count DESCConcepts: inline property filter
{type: 'Engine'}narrows the match before traversing the relationship.
MATCH (s:System)-[:HAS_COMPONENT]->(c:Component)
RETURN s.type AS SystemType,
collect(DISTINCT c.type) AS ComponentTypes,
count(c) AS TotalComponents
ORDER BY TotalComponents DESCConcepts: groups by system type and collects the distinct component types found in each — a quick way to understand what parts belong where.
MATCH (a:Aircraft)-[:HAS_SYSTEM]->(s:System)-[:HAS_COMPONENT]->(c:Component)
RETURN a.tail_number AS Aircraft,
s.name AS System,
s.type AS SystemType,
count(c) AS ComponentCount
ORDER BY ComponentCount DESC
LIMIT 10Concepts: three-hop traversal with aggregation. Shows which specific system instances have the most parts.
MATCH (sn:Sensor)
RETURN sn.type AS SensorType,
sn.unit AS Unit,
count(sn) AS Count
ORDER BY Count DESCConcepts: basic aggregation over Sensor nodes — gives an overview of what's being measured across the fleet.
MATCH (a:Aircraft {tail_number: 'N95040A'})-[:HAS_SYSTEM]->(s:System)-[:HAS_SENSOR]->(sn:Sensor)
WHERE s.type IS NOT NULL AND sn.type IS NOT NULL
RETURN s.name AS System,
s.type AS SystemType,
sn.name AS Sensor,
sn.type AS SensorType,
sn.unit AS Unit
ORDER BY s.type, sn.typeConcepts: three-hop pattern from aircraft through system to sensor.
WHERE ... IS NOT NULLensures sorted properties have values — always filter nulls beforeORDER BY.
MATCH (s:System)-[:HAS_SENSOR]->(sn:Sensor)
WITH s.type AS SystemType, count(sn) AS SensorCount
RETURN SystemType, SensorCount
ORDER BY SensorCount DESCConcepts:
WITHpipes intermediate results forward — here it computes sensor counts per system type, then passes them toRETURNfor sorting.
MATCH (a:Aircraft)-[:HAS_SYSTEM]->(s:System)-[:HAS_COMPONENT]->(c:Component)-[:HAS_EVENT]->(m:MaintenanceEvent)
WHERE m.severity = 'CRITICAL' AND m.reported_at IS NOT NULL
RETURN a.tail_number, s.name, c.name, m.fault, m.reported_at
ORDER BY m.reported_at DESC
LIMIT 10Concepts: four-hop pattern traverses Aircraft → System → Component → MaintenanceEvent in one query.
LIMIT 10caps the output, andORDER BY ... DESCputs the most recent events first.
MATCH (m:MaintenanceEvent)
RETURN m.severity AS Severity, count(m) AS Count
ORDER BY Count DESCConcepts: simple aggregation — quickly shows the distribution of event severities across the dataset.
MATCH (m:MaintenanceEvent)
WHERE m.fault IS NOT NULL
RETURN m.fault AS Fault,
m.severity AS Severity,
count(m) AS Occurrences
ORDER BY Occurrences DESC
LIMIT 15Concepts: groups by fault description and severity to surface the most frequent problems in the fleet.
MATCH (m:MaintenanceEvent)-[:AFFECTS_AIRCRAFT]->(a:Aircraft)
RETURN a.tail_number AS Aircraft,
a.model AS Model,
count(m) AS TotalEvents,
count(CASE WHEN m.severity = 'CRITICAL' THEN 1 END) AS CriticalEvents
ORDER BY TotalEvents DESCConcepts:
CASE WHEN ... THEN 1 ENDinsidecount()acts as a conditional count — only critical events increment the counter, whileNULL(the implicitELSE) is ignored bycount().
MATCH (m:MaintenanceEvent)
WHERE m.severity = 'CRITICAL'
AND m.corrective_action IS NOT NULL
AND m.reported_at IS NOT NULL
RETURN m.fault AS Fault,
m.corrective_action AS CorrectiveAction,
m.reported_at AS ReportedAt
ORDER BY m.reported_at DESC
LIMIT 10Concepts: filters to critical events with recorded fixes — useful for understanding what remediation looks like for the worst problems.
MATCH (m:MaintenanceEvent)-[:AFFECTS_SYSTEM]->(s:System)
RETURN s.type AS SystemType,
count(m) AS Events,
count(CASE WHEN m.severity = 'CRITICAL' THEN 1 END) AS Critical,
count(CASE WHEN m.severity = 'WARNING' THEN 1 END) AS Warning
ORDER BY Events DESCConcepts: uses
AFFECTS_SYSTEMto link events back to the system they impacted. MultipleCASEexpressions in a single query compute severity breakdowns without needing subqueries.
MATCH (f:Flight)-[:HAS_DELAY]->(d:Delay)
RETURN d.cause AS Cause,
count(*) AS Count,
avg(d.minutes) AS AvgMinutes,
max(d.minutes) AS MaxMinutes,
sum(d.minutes) AS TotalMinutes
ORDER BY Count DESCConcepts:
count(*)counts matched rows,avg()/max()/sum()compute statistics — all are grouped byd.cause.
MATCH (f:Flight)
RETURN f.operator AS Operator, count(f) AS FlightCount
ORDER BY FlightCount DESCConcepts: simple aggregation over flight nodes — shows fleet activity by airline.
MATCH (a:Aircraft {tail_number: 'N95040A'})-[:OPERATES_FLIGHT]->(f:Flight)
WHERE f.scheduled_departure IS NOT NULL
OPTIONAL MATCH (f)-[:DEPARTS_FROM]->(dep:Airport)
OPTIONAL MATCH (f)-[:ARRIVES_AT]->(arr:Airport)
RETURN f.flight_number AS Flight,
dep.iata AS Origin,
arr.iata AS Destination,
f.scheduled_departure AS Departure,
f.scheduled_arrival AS Arrival
ORDER BY f.scheduled_departureConcepts: combines
MATCHandOPTIONAL MATCHto pull in origin/destination airports. TheWHEREnull check onscheduled_departuresatisfies the sort — always filter nulls beforeORDER BY.
MATCH (a:Aircraft)-[:OPERATES_FLIGHT]->(f:Flight)-[:HAS_DELAY]->(d:Delay)
WHERE d.minutes IS NOT NULL
RETURN a.tail_number AS Aircraft,
f.flight_number AS Flight,
d.cause AS DelayCause,
d.minutes AS DelayMinutes
ORDER BY d.minutes DESC
LIMIT 10Concepts: three-hop pattern joining aircraft, flight, and delay.
WHERE d.minutes IS NOT NULLensures the sort property has values — always filter nulls beforeORDER BY.
MATCH (a:Aircraft)-[:OPERATES_FLIGHT]->(f:Flight)-[:HAS_DELAY]->(d:Delay)
RETURN a.tail_number AS Aircraft,
a.model AS Model,
count(d) AS DelayCount,
sum(d.minutes) AS TotalDelayMinutes
ORDER BY TotalDelayMinutes DESCConcepts: aggregates delays per aircraft using
sum()— identifies which airframes are causing the most schedule disruption.
MATCH (ap:Airport)
WHERE ap.country IS NOT NULL AND ap.city IS NOT NULL
RETURN ap.iata AS IATA, ap.name AS Name, ap.city AS City, ap.country AS Country
ORDER BY ap.country, ap.cityConcepts: simple node scan with property projection.
WHERE ... IS NOT NULLon sorted columns prevents undefined ordering — always filter nulls beforeORDER BY.
MATCH (f:Flight)-[:DEPARTS_FROM]->(ap:Airport)
RETURN ap.iata AS Airport,
ap.name AS Name,
count(f) AS Departures
ORDER BY Departures DESC
LIMIT 10Concepts: traverses
DEPARTS_FROMand aggregates by airport — shows the hubs with the most outbound flights.
MATCH (f:Flight)-[:DEPARTS_FROM]->(dep:Airport)
MATCH (f)-[:ARRIVES_AT]->(arr:Airport)
RETURN dep.iata AS Origin,
arr.iata AS Destination,
count(f) AS FlightCount
ORDER BY FlightCount DESC
LIMIT 15Concepts: two separate
MATCHclauses share the samefvariable — an alternative to chaining patterns that reads more clearly when the relationships go in different directions.
MATCH (f:Flight)-[:HAS_DELAY]->(d:Delay)
MATCH (f)-[:DEPARTS_FROM]->(ap:Airport)
RETURN ap.iata AS Airport,
ap.name AS Name,
count(d) AS DelayedFlights,
sum(d.minutes) AS TotalDelayMinutes,
avg(d.minutes) AS AvgDelayMinutes
ORDER BY TotalDelayMinutes DESC
LIMIT 10Concepts: joins flights to both delays and departure airports — aggregates delay statistics per airport to find the worst bottlenecks.
MATCH (a:Aircraft)-[:HAS_REMOVAL]->(r:Removal)-[:REMOVED_COMPONENT]->(c:Component)
WHERE r.removal_date IS NOT NULL
RETURN a.tail_number, c.name, r.reason, r.removal_date, r.tsn, r.csn
ORDER BY r.removal_date DESC
LIMIT 20Concepts: three-hop pattern linking aircraft to their removed components.
r.tsn(time since new) andr.csn(cycles since new) are domain properties on the Removal node.
MATCH (r:Removal)
WHERE r.reason IS NOT NULL
RETURN r.reason AS Reason, count(r) AS Count
ORDER BY Count DESCConcepts: aggregation by removal reason — shows the most common causes of part replacement.
MATCH (a:Aircraft)-[:HAS_REMOVAL]->(r:Removal)
RETURN a.tail_number AS Aircraft,
a.model AS Model,
count(r) AS Removals,
avg(r.tsn) AS AvgTimeSinceNew,
avg(r.csn) AS AvgCyclesSinceNew
ORDER BY Removals DESCConcepts: aggregates removal metrics per aircraft —
avg(r.tsn)shows whether parts are being pulled early or late in their lifecycle.
MATCH (r:Removal)-[:REMOVED_COMPONENT]->(c:Component)
RETURN c.type AS ComponentType,
c.name AS ComponentName,
count(r) AS TimesRemoved
ORDER BY TimesRemoved DESC
LIMIT 15Concepts: aggregates from the removal side to find the most failure-prone part types.
These queries traverse multiple domains of the graph to answer questions that span topology, operations, and maintenance.
MATCH (m:MaintenanceEvent {severity: 'CRITICAL'})-[:AFFECTS_AIRCRAFT]->(a:Aircraft)
WITH a, count(m) AS CriticalEvents
MATCH (a)-[:OPERATES_FLIGHT]->(f:Flight)-[:HAS_DELAY]->(d:Delay)
RETURN a.tail_number AS Aircraft,
a.model AS Model,
CriticalEvents,
count(d) AS DelayedFlights,
sum(d.minutes) AS TotalDelayMinutes
ORDER BY CriticalEvents DESCConcepts:
WITHpasses intermediate results (aircraft and their critical event counts) to the nextMATCH. This two-stage pattern is how you correlate data from different parts of the graph.
MATCH (r:Removal)-[:REMOVED_COMPONENT]->(c:Component)-[:HAS_EVENT]->(m:MaintenanceEvent)
WHERE r.removal_date IS NOT NULL
RETURN c.name AS Component,
c.type AS ComponentType,
r.reason AS RemovalReason,
r.removal_date AS RemovedOn,
m.fault AS PriorFault,
m.severity AS FaultSeverity,
m.reported_at AS FaultReportedAt
ORDER BY r.removal_date DESC
LIMIT 20Concepts: links removals back to the maintenance events that preceded them on the same component — useful for understanding whether maintenance flagged a problem before the part was pulled.
MATCH (a:Aircraft {tail_number: 'N95040A'})
OPTIONAL MATCH (a)-[:HAS_SYSTEM]->(s:System)
WITH a, count(s) AS SystemCount
OPTIONAL MATCH (a)-[:OPERATES_FLIGHT]->(f:Flight)
WITH a, SystemCount, count(f) AS FlightCount
OPTIONAL MATCH (a)-[:HAS_REMOVAL]->(r:Removal)
WITH a, SystemCount, FlightCount, count(r) AS RemovalCount
OPTIONAL MATCH (m:MaintenanceEvent)-[:AFFECTS_AIRCRAFT]->(a)
RETURN a.tail_number AS TailNumber,
a.model AS Model,
a.operator AS Operator,
SystemCount,
FlightCount,
RemovalCount,
count(m) AS MaintenanceEventsConcepts: chains
WITHclauses to collect counts from four different relationship types without cross-product inflation. EachOPTIONAL MATCH+WITHstep aggregates one metric before moving on.
MATCH (m:MaintenanceEvent {severity: 'CRITICAL'})-[:AFFECTS_AIRCRAFT]->(a:Aircraft)
WITH DISTINCT a
MATCH (a)-[:OPERATES_FLIGHT]->(f:Flight)-[:DEPARTS_FROM]->(ap:Airport)
WHERE EXISTS { (f)-[:HAS_DELAY]->(:Delay) }
RETURN ap.iata AS Airport,
ap.name AS AirportName,
count(DISTINCT a) AS AffectedAircraft,
count(f) AS DelayedFlights
ORDER BY DelayedFlights DESCConcepts:
EXISTS { }is an existential subquery — it checks whether a pattern exists without returning it.DISTINCTin theWITHclause de-duplicates aircraft before joining to flights.
MATCH (f:Flight)-[:DEPARTS_FROM]->(dep:Airport)
MATCH (f)-[:ARRIVES_AT]->(arr:Airport)
OPTIONAL MATCH (f)-[:HAS_DELAY]->(d:Delay)
MATCH (a:Aircraft)-[:OPERATES_FLIGHT]->(f)
OPTIONAL MATCH (me:MaintenanceEvent)-[:AFFECTS_AIRCRAFT]->(a)
WHERE me.severity = 'CRITICAL'
WITH dep.iata AS Origin,
arr.iata AS Destination,
count(DISTINCT f) AS Flights,
count(DISTINCT d) AS Delays,
count(DISTINCT me) AS CriticalEvents
WHERE Flights > 1
RETURN Origin,
Destination,
Flights,
Delays,
CriticalEvents
ORDER BY Delays DESC
LIMIT 15Concepts: combines route, delay, and maintenance data in a single query. The
WITH ... WHEREpattern filters on aggregated values (routes with more than one flight) — similar to SQL'sHAVING.