Example 7: Polymorphic Objects and Relations with vertex_router and dynamic edge¶
This example demonstrates how to ingest polymorphic entity data from a single objects table and dynamic relations from a relations table, using vertex_router to route rows to the correct vertex types and a dynamic edge step to create edges with types and relation names resolved at extraction time.
Overview¶
The dataset contains:
- objects.csv — One table with mixed entity types (Person, Vehicle, Institution), distinguished by a
typecolumn - relations.csv — One table describing relationships between entities, with source/target types and relation names in columns
Instead of separate resources per entity type, this schema uses:
vertex_router— Routes each objects row to the correct vertex type (person,vehicle,institution) viatype_map- Two
vertex_routersteps on the relations resource — Accumulate source and target vertices into typed slots - A dynamic
edgestep — Creates edges with relation names resolved fromrelation_fieldviarelation_map
Data¶
objects.csv¶
Each row has a type column that determines the vertex type. Shared columns (id, name, etc.) plus type-specific columns (salary for Person, license_plate for Vehicle, etc.):
id,type,name,age,birth_date,email,salary,license_plate,num_wheels,fuel_type,founded_year,num_employees,industry,color,weight_kg,address
ec3cd5f9-8a75-49af-adc8-654eab637ebc,Person,Alice Martin,34.0,1991-02-14,alice@example.com,85000.0,,,,,,,,,12 Rue de Paris
4a4bc6ca-7a1d-49b4-954b-c45a135a4cfa,Vehicle,Toyota Corolla,,,,,AB-123-CD,4.0,Petrol,,,,Blue,1300.0,
eb463fbc-423c-4f82-a532-b21430325f15,Institution,TechNova Labs Europe,,,contact@technova-europe.com,,,,,2012.0,120.0,Biotechnology,,,1 Innovation Drive
relations.csv¶
Each row describes one edge: source_id, target_id, relation_type, source_type, target_type:
source_id,target_id,relation_type,source_type,target_type
ec3cd5f9-8a75-49af-adc8-654eab637ebc,eb463fbc-423c-4f82-a532-b21430325f15,EMPLOYED_BY,Person,Institution
0d1c97b4-2be6-4f9c-af45-1e3a18d1513b,4a4bc6ca-7a1d-49b4-954b-c45a135a4cfa,OWNS,Person,Vehicle
b4dc8ede-2875-4d8b-bfd6-3f07d5eddf5e,eb463fbc-423c-4f82-a532-b21430325f15,FUNDS,Institution,Institution
ec3cd5f9-8a75-49af-adc8-654eab637ebc,01dbf082-514a-4c6b-ae05-b0ec66c30f35,COLLEAGUE_OF,Person,Person
Core Schema Ideas¶
1) vertex_router with type_map (objects resource)¶
vertex_router inspects a type discriminator field and routes each row to the appropriate vertex type:
resources:
- name: objects
pipeline:
- vertex_router:
type_field: type
type_map:
Person: person
Vehicle: vehicle
Institution: institution
type_field: Column whose value selects the vertex typetype_map: Maps raw values (e.g.Person) to vertex type names (e.g.person)
Each row is dispatched to the correct VertexActor for that type. Fields are projected per vertex config; extra columns for other types are ignored.
2) Two vertex_router steps + dynamic edge (relations resource)¶
The relations resource uses two vertex_router steps to accumulate both endpoints, then a dynamic edge step to resolve the edge type at extraction time:
- name: relations
pipeline:
- vertex_router:
type_field: source_type
role: source
from:
id: source_id
type_map:
Person: person
Vehicle: vehicle
Institution: institution
- vertex_router:
type_field: target_type
role: target
from:
id: target_id
type_map:
Person: person
Vehicle: vehicle
Institution: institution
- edge:
source_role: source
target_role: target
relation_field: relation_type
relation_map:
EMPLOYED_BY: employed_by
OWNS: owns
FUNDS: funds
COLLEAGUE_OF: colleague_of
INVESTS_IN: invests_in
role: Names the accumulator slot (lindex.(role, 0)) for eachvertex_routerendpointsource_role/target_role: Match upstreamvertex_router.role; the edge actor finds vertex types by scanning those role slotsfrom: Projects relation-table columns onto vertex fields (e.g.id: source_id), same as on avertexsteprelation_field: Column with the raw relation name (e.g.EMPLOYED_BY)relation_map: Maps raw relation values to canonical names (e.g.EMPLOYED_BY→employed_by)
3) Pre-declare edges for database ingestion¶
When writing to a graph database, declare all edge types in edge_config so collections are created during schema definition:
edge_config:
edges:
- source: person
target: institution
relation: employed_by
- source: person
target: vehicle
relation: owns
- source: institution
target: institution
relation: funds
- source: person
target: person
relation: colleague_of
- source: institution
target: institution
relation: invests_in
The relation names must match the values in relation_map (e.g. employed_by).
Graph Structure¶
The resulting graph has three vertex types and five edge types:
| Vertex | Count | Example |
|---|---|---|
| person | 4 | Alice Martin, Bob Smith |
| vehicle | 3 | Toyota Corolla, Tesla Model 3 |
| institution | 3 | TechNova Labs, FinEdge Capital |
| Edge Type | Source → Target | Example |
|---|---|---|
| employed_by | person → institution | Alice → TechNova Labs |
| owns | person → vehicle | Clara → Toyota Corolla |
| funds | institution → institution | GreenCity → TechNova |
| colleague_of | person → person | Alice → Bob |
| invests_in | institution → institution | FinEdge → TechNova |
Run the Example¶
Key Takeaways¶
vertex_routerroutes polymorphic rows to the correct vertex type using a type discriminator column andtype_map.- Two
vertex_routersteps on a relations resource accumulate both endpoint vertices into named role slots. - The dynamic
edgestep resolves source/target types from those slots and normalizes relation names viarelation_map. source_role/target_roleon theedgestep should equal theroleof the correspondingvertex_routersteps.- Order matters — ingest objects (vertices) before relations (edges) so that edge endpoints exist when edges are created.
Variant: Flat-row pattern¶
When source and target vertices appear in the same row (e.g. a denormalized CSV where each row encodes a complete relationship tuple), the same vertex_router + edge pattern works without any changes. See Example 11 for a fully runnable flat-row example.
Next Steps¶
- Explore vertex_router in the API reference.
- See Example 11 for the flat-row
vertex_router+ dynamicEdgeActorpattern. - See the full example code for the complete implementation.