Model assets as a graph
Most domains are a hierarchy of things that contain or feed each other — a plant contains lines, a line contains machines, a machine emits sensor readings. Model that as resources (the nodes) and relations (the edges), and the SDK returns the persisted graph in one call.
Create the graph
Create the nodes and the edges between them together. Each node needs at least one
label (a type such as Plant or Machine). Relationship-type names and labels are
upper-cased by the server; external ids are not touched at all and are stored exactly as
you send them, so you can mirror the tags your operation already maintains
(COM-99-PT-1034, =K1-M3+B02). The example below uses snake_case because that reads
well in code, not because the server requires it.
External ids & naming →
- Java
- Python
- Rust
ResourceForm plant = new ResourceForm();
plant.setExternalId("plant_oslo");
plant.setName("Oslo Plant");
plant.setLabels(List.of("Plant")); // at least one label is required
ResourceForm line = new ResourceForm();
line.setExternalId("line_a");
line.setName("Assembly line A");
line.setLabels(List.of("Line"));
ResourceForm press = new ResourceForm();
press.setExternalId("press_07");
press.setName("Hydraulic press 07");
press.setLabels(List.of("Machine"));
RelForm plantLine = new RelForm();
plantLine.setName("contains");
plantLine.setFromExternalId("plant_oslo");
plantLine.setToExternalId("line_a");
RelForm lineMachine = new RelForm();
lineMachine.setName("contains");
lineMachine.setFromExternalId("line_a");
lineMachine.setToExternalId("press_07");
var graph = client.resources().create(
List.of(plant, line, press), List.of(plantLine, lineMachine));
System.out.println(graph.getNodes().size() + " nodes, "
+ graph.getRelations().size() + " edges");
import datahub_sdk
nodes = [
datahub_sdk.Resource(external_id="plant_oslo", name="Oslo Plant", labels=["Plant"]),
datahub_sdk.Resource(external_id="line_a", name="Assembly line A", labels=["Line"]),
datahub_sdk.Resource(external_id="press_07", name="Hydraulic press 07", labels=["Machine"]),
]
edges = [
datahub_sdk.RelForm.by_external_ids("plant_oslo", "line_a", "contains"),
datahub_sdk.RelForm.by_external_ids("line_a", "press_07", "contains"),
]
graph = client.resources.create(nodes, edges)
print(len(graph.nodes), "nodes,", len(graph.relations), "edges")
use dataplatform_rust_sdk::resources::Resource;
use dataplatform_rust_sdk::relations::RelForm;
let mut plant = Resource::new();
plant.external_id = "plant_oslo".into();
plant.name = "Oslo Plant".into();
plant.labels = Some(vec!["Plant".into()]); // at least one label is required
let mut line = Resource::new();
line.external_id = "line_a".into();
line.name = "Assembly line A".into();
line.labels = Some(vec!["Line".into()]);
let mut press = Resource::new();
press.external_id = "press_07".into();
press.name = "Hydraulic press 07".into();
press.labels = Some(vec!["Machine".into()]);
let graph = api.resources.create(
vec![plant, line, press],
vec![
RelForm::by_external_ids("plant_oslo", "line_a", "contains"),
RelForm::by_external_ids("line_a", "press_07", "contains"),
],
).await?;
Attach time-series to a node
A machine's sensors are time-series. Tie a series to the machine that produces it
with a relation, exactly as above (press_07 → produces → press_07_oil_temp),
then ingest its datapoints.
Read the graph back
Fetch nodes by external id; each resource carries its outgoing edges.
- Java
- Python
- Rust
var some = client.resources().byIds(List.of(
IdCollection.createFromExternalId("press_07")));
Resource press = some.getItems().iterator().next();
press.getRelations().forEach(edge ->
System.out.println(edge.getType() + " -> " + edge.getEnd()));
press = client.resources.by_ids(["press_07"])[0]
for edge in press.relations:
print(edge.relationship_type, "->", edge.end)
use dataplatform_rust_sdk::generic::IdAndExtId;
let some = api.resources.by_ids(&vec![IdAndExtId::from_external_id("press_07")]).await?;
if let Some(press) = some.nodes().first() {
for edge in press.relations.iter().flatten() {
println!("{} -> {}", edge.relationship_type, edge.end);
}
}
Relations model structure. To slice assets by ownership, environment or tenant — "everything in the Oslo plant" — also put them in a dataset (see the Datasets reference). A resource can sit in a graph and a dataset at once.