Find closely connected communities
The language tabs use earlier client interfaces. Check SDK versions and connection setup before running them.
Louvain groups records with more links inside their group than between groups. One connected component can contain several communities.
Before you run it: IDs can change when the graph changes. Do not use them as permanent business identifiers.
First load the five-person social graph. It creates the exact social.users table and follows relation used below.
A community has relatively many links inside it. Modularity is the score used to compare those groupings; the tolerance controls when further grouping stops.
- Read the self-relationUse the table's linked records.
- Improve the groupingLouvain seeks more links within each community.
- Stop at the configured boundsUse the tolerance and level limits.
- Read community assignmentsGroup record keys that share a community ID.
Follow the example
- Prepare a self-referencing relationship.
- Choose calculation limits.
- Run the community request.
- Inspect rows grouped by community number.
Set up the relationship
The relation must be declared in the schema's [[relations]] block and must target the table it is declared on. louvain refuses a relation that points at another table, and the error names both tables. See schemas/reference#relations.
Run the request
rel is required. tolerance defaults to 1e-4 and stops the calculation when the modularity improvement falls below it. max_levels defaults to 10 and caps the grouping rounds.
curl -G "https://$OC_HOST/v1/tenants/$OC_TENANT/graph/social.users/louvain" \
--data-urlencode "rel=follows" \
--data-urlencode "tolerance=1e-4" \
--data-urlencode "max_levels=10" \
-H "Authorization: Bearer $OC_TOKEN"Check the result
Community numbers identify groups, not a ranking.
{
"communities": [
{ "pk": "alice", "community": 0 },
{ "pk": "bob", "community": 0 },
{ "pk": "carol", "community": 0 },
{ "pk": "dave", "community": 0 },
{ "pk": "heidi", "community": 1 },
{ "pk": "ivan", "community": 1 },
{ "pk": "judy", "community": 1 },
{ "pk": "mallory", "community": 2 }
]
}An object with a single communities array - not a bare array, and not the row shape the other algorithm endpoints use. Here pk is a plain string and community is an integer from 0 through k - 1, where k is the number of detected communities. Ids are assigned in order of first appearance by lexicographic primary key, so the lexicographically smallest key is always in community 0 and a rerun over an unchanged graph produces the same numbering.
Understand the behavior
- Phase one moves each node into whichever neighbouring community gives the largest modularity gain. Phase two collapses each community into a single node and repeats.
- The loop stops when the modularity delta between levels falls below
tolerance, when phase one stops moving nodes, or whenmax_levelsis reached. - Community ids are dense and deterministic, so two runs over the same graph are directly comparable and can be stored as-is.
- The endpoint refuses graphs above its 500,000-node ceiling. The per-level pass is linear in nodes plus edges, and a multi-million-node call will not land inside a request budget.
Important limits and checks
- Reading the response as an array. It is
{ "communities": [ ... ] }. Indexing the body directly gets you nothing. - Expecting
pkto be an array here. louvain returns a plain string, whilecomponents,betweenness,label_propagationandeigenvector_centralityall return a primary-key array. The response grammar genuinely differs per endpoint - write the parser per endpoint. - Comparing community ids across graphs. The numbering comes from this graph's own key order. Ids from a different graph, or from the same graph after new rows land, are not comparable.