OriginChain docs

Schema for Graph algorithms.

schema · graph algorithms

OriginChain ships 19 graph algorithms — neighbors, reverse, BFS, path, all_simple_paths, Dijkstra, k-shortest, PageRank, triangles, components, Louvain, betweenness, eigenvector_centrality, label_propagation, random-walk, Node2Vec (POST + topk), GraphSAGE (POST + topk). Every one operates on a [[relations]] block declared in the schema TOML.

Engine surface: GET /v1/tenants/:t/graph/:schema/<algo>?rel=<name>&… for read algos. POST /…/node2vec | /graphsage for training. GET /…/node2vec/:rel/topk | /graphsage/:rel/topk for persisted-embedding similarity.

Required schema fields.

Without these, this query surface doesn't function at all.

field effect
namespace + table + primary_key + [[columns]] Standard table requirements — algorithms operate on rows in this schema.
[[relations]] with name + from_col The rel= query param on every graph endpoint maps to this name. Without a declared relation, no algorithm runs.
[relations.target] sub-table Algorithms resolve target rows by PK via this descriptor (namespace + table + pk).

Optional fields — what each one unlocks.

Add only the fields whose effect you need. Each one buys a specific capability — speed up a predicate, guard a write, or unlock a new query shape.

field type default effect
[[relations]] bidirectional bool true Required for /reverse, /bfs from target, and any algorithm that traverses against edge direction.
Multiple [[relations]] blocks Each new relation is a new verb in the URL ?rel= param. Same-schema relations unlock the 6 same-schema-only algorithms (triangles, components, louvain, betweenness, eigenvector_centrality, label_propagation).

Which algorithms work on which relation shape.

  • Cross-schema (orders → products): 13 algorithms — neighbors, reverse, bfs, path, all_simple_paths, dijkstra, k-shortest, pagerank, random-walk, node2vec, node2vec/topk, graphsage, graphsage/topk
  • Same-schema (users → users): all 19 algorithms, including triangles, components, louvain, betweenness, eigenvector_centrality, label_propagation

Algorithm limits.

The engine returns a typed 400 with a hint instead of running these. Knowing them up front avoids a debugging round-trip.

shape why
triangles / components / louvain / betweenness / eigenvector_centrality / label_propagation on a CROSS-schema relation Engine returns 400 cross-schema not in v1. Workaround: model the edge as a same-schema relation (e.g. user → user) or compute these client-side.
all_simple_paths_bidir without bidirectional=true Engine returns 400 bidirectional traversal requires bidirectional = true. Either flip the flag or use /all_simple_paths.

Abbreviation legend.

token meaning
rel= URL query param on every /graph/... endpoint — maps to the [[relations]] name field
pk= URL query param for the seed node — value is a row's primary key (e.g. o001)
src= / dst= Source / destination PKs for path / dijkstra / all_simple_paths endpoints
source= / target= Same as src/dst but for /k-shortest (different param names — engine specific)
nodes= Comma-separated seed PK list for pagerank, triangles, components, louvain, etc
max_depth= BFS / path depth cap. Higher = larger frontier
nprobe= / damping= / max_iter= / tol= Algorithm-specific tuning knobs (PageRank, etc)
persist= POST body field on node2vec / graphsage — true persists embeddings so /topk works

Worked example.

Schema TOML — copy + register via POST /v1/tenants/:t/schemas with Content-Type: text/plain.

# Bipartite shape — orders → products
namespace   = "shop"
table       = "orders"
primary_key = ["id"]

[[columns]]
name = "id"          
ty = "str" 
required = true
[[columns]]
name = "customer_id" 
ty = "str" 
required = true
[[columns]]
name = "product_id"  
ty = "str" 
required = true

[[relations]]
name          = "bought_product"
from_col      = "product_id"
bidirectional = true

[relations.target]
namespace = "shop"
table     = "products"
pk        = "id"

# Same-schema shape — users → users (unlocks community + centrality algos)
# Declared on a separate table social.follows
[[relations]]
name          = "follower"
from_col      = "follower_id"
bidirectional = true

[relations.target]
namespace = "social"
table     = "users"
pk        = "id"

Queries it enables.

# Single-hop adjacency
curl "$BASE/v1/tenants/$T/graph/shop.orders/neighbors?rel=bought_product&pk=o001" \
  -H "Authorization: Bearer $BEARER"

# BFS frontier (depth 3)
curl "$BASE/v1/tenants/$T/graph/shop.orders/bfs?rel=bought_product&pk=o001&max_depth=3" \
  -H "Authorization: Bearer $BEARER"

# Reverse — who bought p001? (works because bidirectional=true)
curl "$BASE/v1/tenants/$T/graph/shop.orders/reverse?rel=bought_product&pk=p001" \
  -H "Authorization: Bearer $BEARER"

# Dijkstra (default weight 1.0 — pass weights_json={} for unweighted)
curl "$BASE/v1/tenants/$T/graph/shop.orders/dijkstra?rel=bought_product&src=o001&dst=p001&weights_json=%7B%7D" \
  -H "Authorization: Bearer $BEARER"

# K-shortest (uses source/target — different param names)
curl "$BASE/v1/tenants/$T/graph/shop.orders/k-shortest?rel=bought_product&source=o001&target=p001&k=3" \
  -H "Authorization: Bearer $BEARER"

# PageRank over a seed set
curl "$BASE/v1/tenants/$T/graph/shop.orders/pagerank?rel=bought_product&nodes=o001,o002,o003,o004,o005" \
  -H "Authorization: Bearer $BEARER"

# Node2Vec — train + persist for similarity top-k
curl -X POST $BASE/v1/tenants/$T/graph/shop.orders/node2vec -H "Authorization: Bearer $BEARER" \
  -d '{"rel":"bought_product","dim":16,"walks_per_node":4,"walk_length":6,"window":3,"epochs":1,"p":1.0,"q":1.0,"persist":true}'

curl "$BASE/v1/tenants/$T/graph/shop.orders/node2vec/bought_product/topk?pk=o001&k=5" \
  -H "Authorization: Bearer $BEARER"