Skip to main content

Resources

Hierarchical, asset-like entities and the relationships between them. Create resources and the edges between them in one call; the server returns the persisted graph.

A resource's externalId is its identity: unique per tenant, stored exactly as you send it, and compared without case. Mirror the tag your operation already maintains — COM-99-PT-1034 is stored as COM-99-PT-1034, not rewritten. External ids & naming →

Look up

Fetch by numeric id or external id (you can mix them). Lookup ignores case, so pump_1 and PUMP_1 resolve to the same resource; what comes back keeps the spelling it was created with.

import ai.intellistream.datahub.models.IdCollection;

Resource pump = client.resources().getById(5677892).getItems().iterator().next();

DataWrapper<Resource> some = client.resources().byIds(List.of(
IdCollection.createFromExternalId("pump_1"),
IdCollection.createFromId(5677892)));

Create resources and relations

Pass the resource forms (nodes) and the relation forms (edges); the call returns the created graph — nodes plus server-assigned edges. Each resource needs at least one label (a type tag such as Plant or Pump) — a node with none is rejected with 400 resource.needs.at.least.one.label. Labels and relationship types are both upper-cased by the server. External ids are not: they are stored verbatim.

The call is all-or-nothing. Every external id in the batch is validated before anything is written, so one item rejected by the naming policy means nothing is created and the 400 names every offending item, not just the first. If the policy is set to warn instead, the response carries a warnings array next to items.

Edges into datasets and time-series are validated

Two endpoint rules apply to every edge, on create and on update (an update can retarget an edge or change its type):

  • A relation to a dataset must use the BELONGS_TO relationship type — that is the relation the dataset hierarchy and membership are built from, and anything else is rejected with a 400.
  • A dataset → time-series edge is accepted only when the series has no dataset yet, or already belongs to that very dataset (creating a series inside a dataset produces exactly that membership edge). A series in a different dataset is rejected with a 400 — a time-series has one dataset.
ResourceForm plant = new ResourceForm();
plant.setExternalId("plant_oslo");
plant.setName("Oslo Plant");
plant.setLabels(List.of("Plant"));

ResourceForm pump = new ResourceForm();
pump.setExternalId("pump_1");
pump.setName("Pump 1");
pump.setLabels(List.of("Pump"));

RelForm contains = new RelForm();
contains.setName("contains");
contains.setFromExternalId("plant_oslo");
contains.setToExternalId("pump_1");

GraphDataWrapper<Resource, EdgeProxy> created = client.resources()
.create(List.of(plant, pump), List.of(contains));

System.out.println(created.getNodes().size() + " resources, "
+ created.getRelations().size() + " relations");

Free-text / fuzzy search across resources.

ResourceSearch search = new ResourceSearch();
search.setLimit(10);
search.getSearch().setQuery("pump");
DataWrapper<Resource> matches = client.resources().search(search);

Use filter(new ResourceRetreiver()) for structured filters (labels, metadata, parent).

Delete

Delete by id or external id; returns the removed graph.

client.resources().delete(List.of(IdCollection.createFromExternalId("pump_1")));

Traverse the graph

fetchRelated walks the graph outward from a starting resource and returns the connected sub-graph — a ResourceNetwork of nodes, the edges between them, and their labels. Traversal is undirected and bounded by depth (-1 = the whole connected component), optionally filtered to specific relationship types. Use it for relationship reasoning — root-cause correlation, blast radius — that a flat lookup can't do. See Correlate alarms with the graph.

// convenience: within `depth` hops of an external id
ResourceNetwork net = client.resources().fetchRelated("sensor_a", 5);

// or the full form, filtering which relationship types to follow
RelatedResourcesForm form = new RelatedResourcesForm();
form.setExternalId("sensor_a");
form.setDepth(5);
form.setRelationshipTypes(List.of("PART_OF"));
ResourceNetwork filtered = client.resources().fetchRelated(form);

net.nodes().forEach(n -> System.out.println(n.getExternalId()));