13. eigenvector_centrality - influence by association
← Graph exampleswhat this does
eigenvector_centrality scores a node by the scores of the nodes attached to it, so being pointed at by three important nodes counts for more than being pointed at by thirty unimportant ones. GET /v1/tenants/:t/graph/:schema/eigenvector_centrality runs power iteration over the relation and returns one row per node, sorted descending. Unlike pagerank, it needs no node universe: it scores whatever is in the table.
when to use it
- Ranking influence across a whole table without having to choose the candidate set first, which is what
pagerankmakes you do. - Prestige-style scoring, where an endorsement from an already-central node should count for more than one from the periphery.
- A cheap global ranking used to seed a more expensive per-candidate model.
schema requirement
The relation must be declared in the schema's [[relations]] block and must target the table it is declared on. See schemas/reference#relations.
the request
rel is required. max_iter (default 50) bounds the power iteration and tol (default 1e-6) is the convergence threshold. max_iter=0 is refused with a 400.
curl -G "https://$OC_HOST/v1/tenants/$OC_TENANT/graph/social.users/eigenvector_centrality" \
--data-urlencode "rel=follows" \
--data-urlencode "max_iter=50" \
--data-urlencode "tol=1e-6" \
-H "Authorization: Bearer $OC_TOKEN"# The Python SDK does not wrap this endpoint - call it directly.
import httpx
r = httpx.get(
f"https://{OC_HOST}/v1/tenants/{OC_TENANT}"
"/graph/social.users/eigenvector_centrality",
params={"rel": "follows", "max_iter": 50, "tol": 1e-6},
headers={"Authorization": f"Bearer {OC_TOKEN}"},
)
top = [(row["pk"][0], row["eigenvector"]) for row in r.json()[:10]]// The TypeScript SDK does not wrap the graph algorithms - use fetch.
const qs = new URLSearchParams({
rel: "follows",
max_iter: "50",
tol: "1e-6",
});
const res = await fetch(
`https://${OC_HOST}/v1/tenants/${OC_TENANT}/graph/social.users/eigenvector_centrality?${qs}`,
{ headers: { Authorization: `Bearer ${OC_TOKEN}` } },
);
const ranked = await res.json();// The Go SDK does not wrap the graph algorithms - use net/http.
url := "https://" + OC_HOST + "/v1/tenants/" + OC_TENANT +
"/graph/social.users/eigenvector_centrality?rel=follows&max_iter=50"
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
req.Header.Set("Authorization", "Bearer "+OC_TOKEN)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var ranked []struct {
PK []string `json:"pk"`
Eigenvector float64 `json:"eigenvector"`
}
json.NewDecoder(resp.Body).Decode(&ranked)what you get back
[
{ "pk": ["dave"], "eigenvector": 0.51 },
{ "pk": ["carol"], "eigenvector": 0.44 },
{ "pk": ["bob"], "eigenvector": 0.36 },
{ "pk": ["alice"], "eigenvector": 0.29 },
{ "pk": ["mallory"], "eigenvector": 0.0 }
]
One row per node, sorted by score descending. pk is the primary-key array and the score field is named eigenvector. The score field name differs on every centrality endpoint - betweenness returns betweenness and pagerank returns score - so a shared parser has to know which endpoint produced the body it is holding.
how it works
- Power iteration: start from a uniform vector, multiply repeatedly by the adjacency matrix, renormalise, and stop when the change falls below
tolor aftermax_iterrounds. - The iteration runs on the adjacency matrix plus the identity rather than the adjacency matrix alone. That shift is what stops a bipartite graph oscillating between two states and never converging.
- Scores are relative, not absolute. Only the ordering and the ratios between scores carry meaning.
- No node universe is required, which is the practical difference from
pagerank: pagerank makes you name the subgraph up front, this endpoint scores the table as it stands.
common mistakes
- Expecting pagerank's numbers. Eigenvector centrality has no damping factor and no random-restart term, so it concentrates far more weight on the densest region of the graph. The two rankings will differ and neither is wrong.
- Reading a zero as a bug. A node with no inbound edges receives no weight. Isolated rows legitimately score zero.
- Reusing a betweenness parser. The score field is called
eigenvectorhere, and readingrow.betweennessgives you nothing.