Aerospace — fleet predictive maintenance
The problem. An airline operates a fleet of aircraft, each a deep hierarchy of systems and components, each component streaming sensor data every second of every flight. When one part starts trending toward failure, two questions follow immediately: is this part about to fail, and which other aircraft carry the same part and are therefore at the same risk? The second question is a graph question — and answering it fast is the difference between scheduled maintenance and a grounding.
This scenario leans on the knowledge graph: model the fleet down to the component, and when one component looks suspect, walk the graph to its whole blast radius.
Set up demo data
New workspace? Run this once (Python) to create three aircraft whose pumps are all the same part type — so the blast-radius walk in step 2 returns the whole affected fleet. Safe to re-run.
import datahub_sdk
client = datahub_sdk.DataHubClient.from_env()
nodes = [datahub_sdk.Resource(external_id="part_type_hp_47", name="Hydraulic pump type HP-47", labels=["part_type_hp_47"])]
edges = []
for ac in ["ln_312", "ln_318", "ln_401"]:
nodes += [datahub_sdk.Resource(external_id=f"aircraft_{ac}", name=f"Aircraft {ac}", labels=[f"aircraft_{ac}"]),
datahub_sdk.Resource(external_id=f"hyd_pump_{ac}_1", name=f"Pump {ac}", labels=[f"hyd_pump_{ac}_1"])]
edges += [datahub_sdk.RelForm.by_external_ids(f"aircraft_{ac}", f"hyd_pump_{ac}_1", "contains"),
datahub_sdk.RelForm.by_external_ids(f"hyd_pump_{ac}_1", "part_type_hp_47", "is_part_type")]
client.resources.create(nodes, edges)
1. Model the fleet to the component
A fleet contains aircraft, an aircraft contains systems, a system contains
components. Components of the same part type also link to a shared part_type node —
that shared node is what makes fleet-wide correlation possible.
- Java
- Python
- Rust
ResourceForm aircraft = new ResourceForm();
aircraft.setExternalId("aircraft_ln_312");
aircraft.setName("Aircraft LN-312");
aircraft.setLabels(List.of("aircraft_ln_312"));
ResourceForm pump = new ResourceForm();
pump.setExternalId("hyd_pump_ln_312_1");
pump.setName("Hydraulic pump #1");
pump.setLabels(List.of("hyd_pump_ln_312_1"));
// the component is an instance of a shared part type
RelForm installed = new RelForm();
installed.setName("contains");
installed.setFromExternalId("aircraft_ln_312");
installed.setToExternalId("hyd_pump_ln_312_1");
RelForm isType = new RelForm();
isType.setName("is_part_type");
isType.setFromExternalId("hyd_pump_ln_312_1");
isType.setToExternalId("part_type_hp_47");
client.resources().create(List.of(aircraft, pump), List.of(installed, isType));
import datahub_sdk
client.resources.create(
[datahub_sdk.Resource(external_id="aircraft_ln_312", name="Aircraft LN-312", labels=["aircraft_ln_312"]),
datahub_sdk.Resource(external_id="hyd_pump_ln_312_1", name="Hydraulic pump #1", labels=["hyd_pump_ln_312_1"])],
[datahub_sdk.RelForm.by_external_ids("aircraft_ln_312", "hyd_pump_ln_312_1", "contains"),
datahub_sdk.RelForm.by_external_ids("hyd_pump_ln_312_1", "part_type_hp_47", "is_part_type")])
use dataplatform_rust_sdk::resources::Resource;
use dataplatform_rust_sdk::relations::RelForm;
let mut aircraft = Resource::new();
aircraft.external_id = "aircraft_ln_312".into();
aircraft.name = "Aircraft LN-312".into();
aircraft.labels = Some(vec!["aircraft_ln_312".into()]);
let mut pump = Resource::new();
pump.external_id = "hyd_pump_ln_312_1".into();
pump.name = "Hydraulic pump #1".into();
pump.labels = Some(vec!["hyd_pump_ln_312_1".into()]);
api.resources.create(
vec![aircraft, pump],
vec![
RelForm::by_external_ids("aircraft_ln_312", "hyd_pump_ln_312_1", "contains"),
RelForm::by_external_ids("hyd_pump_ln_312_1", "part_type_hp_47", "is_part_type"),
],
).await?;
Each component streams series — hyd_pump_ln_312_1_vibration_mm_s,
hyd_pump_ln_312_1_temp_c — ingested at fleet scale.
2. A part looks suspect — find the blast radius
Rising vibration on one pump suggests a part-type defect. Walk the graph out from the
shared part_type_hp_47 node: every component is_part_type of it, and every
aircraft that contains one, is the blast radius — the list maintenance needs to
inspect.
- Java
- Python
- Rust
ResourceNetwork affected = client.resources().fetchRelated("part_type_hp_47", 3);
// every aircraft in the returned sub-graph carries this part type
affected.nodes().stream()
.filter(n -> n.getExternalId().startsWith("aircraft_"))
.forEach(a -> System.out.println("inspect: " + a.getExternalId()));
affected = client.resources.fetch_related(external_id="part_type_hp_47", depth=3)
for node in affected.nodes:
if node.external_id.startswith("aircraft_"):
print("inspect:", node.external_id)
use dataplatform_rust_sdk::resources::RelatedResourcesForm;
let affected = api.resources.fetch_related(
&RelatedResourcesForm::from_external_id("part_type_hp_47").with_depth(3)).await?;
for node in affected.nodes() {
if node.external_id.starts_with("aircraft_") {
println!("inspect: {}", node.external_id);
}
}
One traversal turns a single suspect reading into a precise, fleet-wide inspection list. See Correlate alarms with the graph for the pattern.
3. Record the finding
Raise a component_anomaly event per affected component so the maintenance system
schedules the work and keeps an auditable trail.
See the result
Walking out from the suspect part type returns every aircraft to inspect:
inspect: aircraft_ln_312
inspect: aircraft_ln_318
inspect: aircraft_ln_401
See also
- Model assets as a graph — the fleet/aircraft/component hierarchy.
- Correlate alarms with the graph — blast-radius traversal in detail.
- High-throughput ingestion — per-flight sensor volume.
- Turn readings into events — the anomaly rule.
- Predictive maintenance (advanced) — learn a component's healthy vibration signature and flag the drift.