Skip to content

Graph Algorithms Reference

GraphQLite provides 18 built-in graph algorithms accessible via Cypher functions, the Python Graph API, and the Rust Graph API.

For guidance on choosing the right algorithm for your use case, see Using Graph Algorithms.

In Cypher, you can call an algorithm in two forms. The comment under each signature shows the keys of the result objects.

CALL form. The query gives one row for each result object. YIELD selects the keys, and AS can rename them. YIELD ... WHERE filters the rows. Other clauses can follow:

CALL pageRank() YIELD user_id, score
RETURN user_id, score ORDER BY score DESC LIMIT 10
CALL pageRank() YIELD node_id, score
MATCH (n) WHERE id(n) = node_id
SET n.rank = score

Without YIELD, the query gives every key. A key that the algorithm does not give is an error. dijkstra and astar give one row. A CALL of a name that is not an algorithm gives ProcedureError: ProcedureNotFound. The CALL must be the first clause of the query.

Function form. Use the algorithm as a function in a RETURN clause with no other clause. The query gives one row. The value is a JSON array of result objects, or one JSON object for dijkstra and astar. The column is column_0, or the alias of RETURN pageRank() AS pr. To get one row for each result in SQL, use json_each:

SELECT json_extract(value, '$.user_id') AS user_id,
json_extract(value, '$.score') AS score
FROM json_each(cypher('RETURN pageRank(0.85, 20)'), '$[0].column_0');

Cypher

RETURN pageRank([damping, iterations])
// [{node_id, user_id, score}, ...]

Python

graph.pagerank(damping=0.85, iterations=20)

Rust

graph.pagerank(damping: f64, iterations: usize) -> Result<Vec<PageRankResult>>

Parameters

Parameter Type Default Description
damping Float 0.85 Damping factor
iterations Integer 20 Number of power iterations

Return shape

Python: list[dict] with keys node_id, user_id, score

Rust: Vec<PageRankResult> — fields: node_id: i64, user_id: String, score: f64

Complexity: O(iterations × (V + E))

Example

results = graph.pagerank(damping=0.85, iterations=30)
for r in sorted(results, key=lambda x: x['score'], reverse=True)[:5]:
print(r['user_id'], r['score'])

Cypher

RETURN degreeCentrality()
// [{node_id, user_id, in_degree, out_degree, degree}, ...]

Python

graph.degree_centrality()

Rust

graph.degree_centrality() -> Result<Vec<DegreeCentralityResult>>

Parameters: none

Return shape

Python: list[dict] with keys node_id, user_id, in_degree, out_degree, degree

Rust: Vec<DegreeCentralityResult> — fields: node_id: i64, user_id: String, in_degree: usize, out_degree: usize, degree: usize

Complexity: O(V + E)

Example

for r in graph.degree_centrality():
print(r['user_id'], 'in:', r['in_degree'], 'out:', r['out_degree'])

Cypher

RETURN betweennessCentrality()
// [{node_id, user_id, score}, ...]

Python

graph.betweenness_centrality()

Rust

graph.betweenness_centrality() -> Result<Vec<BetweennessCentralityResult>>

Parameters: none

Return shape

Python: list[dict] with keys node_id, user_id, score

Rust: Vec<BetweennessCentralityResult> — fields: node_id: i64, user_id: String, score: f64

Complexity: O(V × E)

Example

results = graph.betweenness_centrality()

Cypher

RETURN closenessCentrality()
// [{node_id, user_id, score}, ...]

Python

graph.closeness_centrality()

Rust

graph.closeness_centrality() -> Result<Vec<ClosenessCentralityResult>>

Parameters: none

Return shape

Python: list[dict] with keys node_id, user_id, score

Rust: Vec<ClosenessCentralityResult> — fields: node_id: i64, user_id: String, score: f64

Complexity: O(V × (V + E))

Example

results = graph.closeness_centrality()

Cypher

RETURN eigenvectorCentrality([iterations])
// [{node_id, user_id, score}, ...]

Python

graph.eigenvector_centrality(iterations=100)

Rust

graph.eigenvector_centrality(iterations: usize) -> Result<Vec<EigenvectorCentralityResult>>

Parameters

Parameter Type Default Description
iterations Integer 100 Power iteration count

Return shape

Python: list[dict] with keys node_id, user_id, score

Rust: Vec<EigenvectorCentralityResult> — fields: node_id: i64, user_id: String, score: f64

Complexity: O(iterations × E)


Cypher

RETURN louvain([resolution])
// [{node_id, user_id, community}, ...]

Python

graph.louvain(resolution=1.0)

Rust

graph.louvain(resolution: f64) -> Result<Vec<CommunityResult>>

Parameters

Parameter Type Default Description
resolution Float 1.0 Resolution parameter controlling community granularity

Return shape

Python: list[dict] with keys node_id, user_id, community

Rust: Vec<CommunityResult> — fields: node_id: i64, user_id: String, community: i64

Example

communities = graph.louvain(resolution=0.5)

Python only

graph.leiden_communities(resolution=1.0, random_seed=None)

Parameters

Parameter Type Default Description
resolution Float 1.0 Resolution parameter
random_seed Integer | None None Seed for reproducibility

Return shape: list[dict] with keys node_id, user_id, community


Cypher

RETURN labelPropagation([iterations])
// [{node_id, user_id, community}, ...]

Python

graph.community_detection(iterations=10)

Rust

graph.community_detection(iterations: usize) -> Result<Vec<CommunityResult>>

Parameters

Parameter Type Default Description
iterations Integer 10 Maximum iterations

Return shape

Python: list[dict] with keys node_id, user_id, community

Rust: Vec<CommunityResult> — fields: node_id: i64, user_id: String, community: i64


Cypher

RETURN weaklyConnectedComponents()
// [{node_id, user_id, component}, ...]

Python

graph.weakly_connected_components()

Rust

graph.weakly_connected_components() -> Result<Vec<ComponentResult>>

Parameters: none

Return shape

Python: list[dict] with keys node_id, user_id, component

Rust: Vec<ComponentResult> — fields: node_id: i64, user_id: String, component: i64

Complexity: O(V + E)


Cypher

RETURN stronglyConnectedComponents()
// [{node_id, user_id, component}, ...]

Python

graph.strongly_connected_components()

Rust

graph.strongly_connected_components() -> Result<Vec<ComponentResult>>

Parameters: none

Return shape

Python: list[dict] with keys node_id, user_id, component

Rust: Vec<ComponentResult> — fields: node_id: i64, user_id: String, component: i64

Complexity: O(V + E) (Tarjan or Kosaraju)


Cypher (path function)

MATCH p = shortestPath((a)-[*]->(b))
RETURN p

Cypher (Dijkstra)

RETURN dijkstra(source, target[, weight_property])
// {path, distance, found}

Python

graph.shortest_path(source, target, weight_property=None)

Rust

graph.shortest_path(source: &str, target: &str, weight_property: Option<&str>) -> Result<ShortestPathResult>

Parameters

Parameter Type Default Description
source String required Source node user ID
target String required Target node user ID
weight_property String | None None Edge property to use as weight; unweighted BFS if None

Return shape

Python: dict with keys path (list of user IDs), distance (float), found (bool)

Rust: ShortestPathResult — fields: path: Vec<String>, distance: f64, found: bool

Example

result = graph.shortest_path('alice', 'bob', weight_property='cost')
if result['found']:
print(result['path'], result['distance'])

Cypher

RETURN astar(source, target[, lat_prop, lon_prop])
// {path, distance, found, nodes_explored}

Python

graph.astar(source, target, lat_prop=None, lon_prop=None)

Rust

graph.astar(source: &str, target: &str, lat_prop: Option<&str>, lon_prop: Option<&str>) -> Result<AStarResult>

Parameters

Parameter Type Default Description
source String required Source node user ID
target String required Target node user ID
lat_prop String | None None Node property for latitude
lon_prop String | None None Node property for longitude

Return shape

Python: dict with keys path, distance, found, nodes_explored

Rust: AStarResult — fields: path: Vec<String>, distance: f64, found: bool, nodes_explored: usize


Cypher

RETURN apsp()
// [{source, target, distance}, ...]

Python

graph.all_pairs_shortest_path()

Rust

graph.all_pairs_shortest_path() -> Result<Vec<ApspResult>>

Parameters: none

Return shape

Python: list[dict] with keys source, target, distance

Rust: Vec<ApspResult> — fields: source: String, target: String, distance: f64

Complexity: O(V × (V + E))


Cypher

RETURN bfs(start[, max_depth])
// [{node_id, user_id, depth, order}, ...]

Python

graph.bfs(start, max_depth=-1)

Rust

graph.bfs(start: &str, max_depth: i64) -> Result<Vec<TraversalResult>>

Parameters

Parameter Type Default Description
start String required Starting node user ID
max_depth Integer -1 Maximum depth; -1 means unlimited

Return shape

Python: list[dict] with keys user_id, depth, order

Rust: Vec<TraversalResult> — fields: user_id: String, depth: usize, order: usize


Cypher

RETURN dfs(start[, max_depth])
// [{node_id, user_id, depth, order}, ...]

Python

graph.dfs(start, max_depth=-1)

Rust

graph.dfs(start: &str, max_depth: i64) -> Result<Vec<TraversalResult>>

Parameters

Parameter Type Default Description
start String required Starting node user ID
max_depth Integer -1 Maximum depth; -1 means unlimited

Return shape: same as BFS — list[dict] / Vec<TraversalResult> with user_id, depth, order


Cypher

RETURN nodeSimilarity() // all pairs
RETURN nodeSimilarity(threshold[, top_k]) // pairs at or above threshold
RETURN nodeSimilarity(node1, node2) // one pair
// [{node1, node2, similarity}, ...]

Python

graph.node_similarity(node1_id=None, node2_id=None, threshold=0.0, top_k=0)

Rust

graph.node_similarity(node1_id: Option<i64>, node2_id: Option<i64>, threshold: f64, top_k: usize) -> Result<Vec<NodeSimilarityResult>>

Parameters

Parameter Type Default Description
node1_id Integer | None None Fix first node; None means all pairs
node2_id Integer | None None Fix second node; None means all pairs
threshold Float 0.0 Minimum similarity to include
top_k Integer 0 Return at most top_k results; 0 means all

Algorithm: Jaccard similarity based on shared neighbors.

Limits: with threshold > 0 only pairs that share at least one neighbor can qualify, so candidates are enumerated through shared neighbors and graphs up to 50,000 nodes are accepted. With threshold = 0 every pair (including similarity 0.0) is part of the result, which is O(N²) by definition, so all-pairs mode is capped at 5,000 nodes; use a threshold, top_k, or the specific-pair form above that.

Return shape

Python: list[dict] with keys node1, node2, similarity

Rust: Vec<NodeSimilarityResult> — fields: node1: String, node2: String, similarity: f64


Cypher

RETURN knn(node, k)
// [{neighbor, similarity, rank}, ...]

Python

graph.knn(node_id, k=10)

Rust

graph.knn(node_id: i64, k: usize) -> Result<Vec<KnnResult>>

Parameters

Parameter Type Default Description
node_id Integer required Source node internal ID
k Integer 10 Number of neighbors to return

Return shape

Python: list[dict] with keys neighbor, similarity, rank

Rust: Vec<KnnResult> — fields: neighbor: String, similarity: f64, rank: usize


Cypher

RETURN triangleCount()
// [{node_id, user_id, triangles, clustering_coefficient}, ...]

Python

graph.triangle_count()

Rust

graph.triangle_count() -> Result<Vec<TriangleCountResult>>

Parameters: none

Return shape

Python: list[dict] with keys node_id, user_id, triangles, clustering_coefficient

Rust: Vec<TriangleCountResult> — fields: node_id: i64, user_id: String, triangles: usize, clustering_coefficient: f64

Complexity: O(V × degree²)

Example

for r in graph.triangle_count():
print(r['user_id'], r['triangles'], r['clustering_coefficient'])