OriginChainDB docs
examples · graph · 8 / 17

8. triangles - every closed triple in a relation

← Graph examples

what this does

triangles enumerates every closed triple in one table's own relation graph. GET /v1/tenants/:t/graph/:schema/triangles takes a single rel parameter, symmetrises the relation so an edge counts in both directions, and returns one row per triangle with the three primary keys in canonical order.

when to use it

  • Mutual-connection detection. Three accounts that all reference each other is a far stronger signal than three that merely share a neighbour.
  • Local density analytics. Triangle count over a node's degree is the standard clustering-coefficient measure.
  • Ring detection in payments, referrals and reciprocal-link networks, where the closed triple is exactly the shape you are hunting for.

schema requirement

The relation must be declared in the schema's [[relations]] block and must target the table it is declared on - triangle enumeration walks one table's own edge set, and a relation pointing at another table is refused. See schemas/reference#relations.

the request

rel is the only parameter this endpoint accepts. There is no depth, no start node and no cap: the answer is every triangle in the relation.

GET /v1/tenants/:t/graph/:schema/triangles?rel=...
curl -G "https://$OC_HOST/v1/tenants/$OC_TENANT/graph/social.users/triangles" \
  --data-urlencode "rel=follows" \
  -H "Authorization: Bearer $OC_TOKEN"

what you get back

[
  { "a": ["alice"], "b": ["bob"],  "c": ["carol"] },
  { "a": ["heidi"], "b": ["ivan"], "c": ["judy"] }
]

One object per triangle. a, b and c are primary-key arrays, not strings - the array is what a composite primary key needs, so a single-column key arrives as a one-element array. The three keys come back in canonical order, so the same triangle is always reported the same way and you can deduplicate on the triple.

how it works

  • The relation is symmetrised before enumeration, so a triangle is found whether its three edges point around the ring or at each other.
  • Enumeration runs inside the query executor rather than as a standalone library call, so it inherits the same cancellation and result-budget handling as the rest of the read path.
  • A self-loop is not an edge for this purpose and contributes no triangle.
  • On a graph big enough to blow the scan budget the request is refused with a tagged graph_work_budget_exceeded 400 instead of being allowed to exhaust memory.

common mistakes

  • Expecting direction to matter. The relation is walked as undirected. alice pointing at bob and bob pointing at alice are the same edge here. If direction is the question, triangles is the wrong endpoint.
  • Reading a as a string. Each of a, b and c is an array. For a single-column primary key you want row.a[0].
  • Pointing rel at another table. The relation has to target the table it is declared on. A cross-table relation is refused rather than quietly returning nothing.