Inline records¶
kglite.from_records() is the JSON-native loader for agents, APIs, and small
in-memory payloads. It builds nodes and relationships without temporary CSVs.
import kglite
graph = kglite.from_records({
"nodes": [{
"type": "Person",
"id_field": "id",
"title_field": "name",
"records": [{"id": 1, "name": "Alice", "tags": ["reviewer"]}],
}],
"connections": [{
"type": "KNOWS",
"source_type": "Person",
"source_id_field": "source",
"target_type": "Person",
"target_id_field": "target",
"records": [{"source": 1, "target": 2, "since": 2024}],
}],
}, on_missing_endpoint="vivify")
The key sets above are closed — nodes, connections and
on_missing_endpoint at the top level, and the per-spec keys shown. An unknown
key raises a ValueError naming a near-miss where there is one, because a key
the loader does not read would otherwise be dropped in silence: a spec written
with "relationships" builds no relationships at all.
A node spec may also carry "labels": ["Human", "Agent"] — secondary labels
stamped on every node of that type, including endpoint stubs vivify created
for it, so MATCH (:Human) sees the whole type. Listing the type’s own name is
a no-op, not a duplicate.
JSON arrays/maps become native list/map values. on_missing_endpoint can be
written in the spec (as above) or passed as the argument, which overrides the
spec’s value when given; it is:
"vivify"(default) — create provisional endpoint stubs."drop"— skip relationships whose source/target is absent and report them."error"— validate the complete input and fail atomically before applying any block when an endpoint is absent.
A connection spec’s target_type also takes a list, for a relationship
whose range is a union of node types:
{
"type": "ASSOCIATED_WITH",
"source_type": "Microbe",
"source_id_field": "source",
"target_type": ["Disease", "Phenotype", "Exposure"],
"target_type_column": "kind",
"target_id_field": "target",
"records": [{"source": "M1", "target": "D1", "kind": "Disease"}],
}
target_type_column names the record field holding each record’s target type;
without it the listed types are probed for the record’s target id and the first
that has it wins, an id none has taking the first listed type. Values are
closed like the keys are: a record naming a type outside the list raises,
where the blueprint loader — whose CSVs are not authored by the caller in the
same breath — warns and skips the row.
Use from_blueprint() for repeatable CSV pipelines with compute operations;
use DataFrame bulk loaders for already-tabular/high-volume Python data.
Embedded table vs row nodes¶
Nested lists/maps loaded through from_records can also live as embedded
table properties or as row nodes — the decision table, the declared-shape
validation, and the attach_rows helper are in Structured data (tables, nested values, shapes).