This section describes the PageRank algorithm in the Neo4j Graph Data Science library.
This topic includes:
The PageRank algorithm measures the importance of each node within the graph, based on the number incoming relationships and the importance of the corresponding source nodes. The underlying assumption roughly speaking is that a page is only as important as the pages that link to it.
PageRank is introduced in the original Google paper as a function that solves the following equation:
where,
This equation is used to iteratively update a candidate solution and arrive at an approximate solution to the same equation.
For more information on this algorithm, see:
Running this algorithm requires sufficient memory availability. Before running this algorithm, we recommend that you read Section 3.1, “Memory Estimation”. 
There are some things to be aware of when using the PageRank algorithm:
Changing the value of damping factor can help with these considerations. It can be interpreted as a probability of a web surfer to sometimes jump to a random page and therefore not getting stuck in sinks.
This section covers the syntax used to execute the PageRank algorithm in each of its execution modes. We are describing the named graph variant of the syntax. To learn more about general syntax variants, see Section 6.1, “Syntax overview”.
Run PageRank in stream mode on a named graph.
CALL gds.pageRank.stream(
graphName: String,
configuration: Map
)
YIELD
nodeId: Integer,
score: Float
Name  Type  Default  Optional  Description 

graphName 
String 

no 
The name of a graph stored in the catalog. 
configuration 
Map 

yes 
Configuration for algorithmspecifics and/or graph filtering. 
Name  Type  Default  Optional  Description 

nodeLabels 
String[] 

yes 
Filter the named graph using the given node labels. 
String[] 

yes 
Filter the named graph using the given relationship types. 

Integer 

yes 
The number of concurrent threads used for running the algorithm. 
Name  Type  Default  Optional  Description 

dampingFactor 
Float 

yes 
The damping factor of the Page Rank calculation. Must be in [0, 1). 
Integer 

yes 
The maximum number of iterations of Page Rank to run. 

Float 

yes 
Minimum change in scores between iterations. If all scores change less than the tolerance value the result is considered stable and the algorithm returns. 

String 

yes 
If set, the values stored at the given property are used as relationship weights during the computation. If not set, the graph is considered unweighted. 

sourceNodes 
List 

yes 
A set of nodes to use for computing Personalized Page Rank. 
Name  Type  Description 

nodeId 
Integer 
Node ID. 
score 
Float 
PageRank score. 
Run PageRank in stats mode on a named graph.
CALL gds.pageRank.stats(
graphName: String,
configuration: Map
)
YIELD
ranIterations: Integer,
didConverge: Boolean,
createMillis: Integer,
computeMillis: Integer,
postProcessingMillis: Integer,
centralityDistribution: Map,
configuration: Map
Name  Type  Default  Optional  Description 

graphName 
String 

no 
The name of a graph stored in the catalog. 
configuration 
Map 

yes 
Configuration for algorithmspecifics and/or graph filtering. 
Name  Type  Default  Optional  Description 

nodeLabels 
String[] 

yes 
Filter the named graph using the given node labels. 
String[] 

yes 
Filter the named graph using the given relationship types. 

Integer 

yes 
The number of concurrent threads used for running the algorithm. 
Name  Type  Default  Optional  Description 

dampingFactor 
Float 

yes 
The damping factor of the Page Rank calculation. Must be in [0, 1). 
Integer 

yes 
The maximum number of iterations of Page Rank to run. 

Float 

yes 
Minimum change in scores between iterations. If all scores change less than the tolerance value the result is considered stable and the algorithm returns. 

String 

yes 
If set, the values stored at the given property are used as relationship weights during the computation. If not set, the graph is considered unweighted. 

sourceNodes 
List 

yes 
A set of nodes to use for computing Personalized Page Rank. 
Name  Type  Description 

ranIterations 
Integer 
The number of iterations run. 
didConverge 
Boolean 
Indicates if the algorithm converged. 
createMillis 
Integer 
Milliseconds for creating the graph. 
computeMillis 
Integer 
Milliseconds for running the algorithm. 
postProcessingMillis 
Integer 
Milliseconds for computing the 
centralityDistribution 
Map 
Map containing min, max, mean as well as p50, p75, p90, p95, p99 and p999 percentile values of centrality values. 
configuration 
Map 
The configuration used for running the algorithm. 
Run PageRank in mutate mode on a named graph.
CALL gds.pageRank.mutate(
graphName: String,
configuration: Map
)
YIELD
nodePropertiesWritten: Integer,
ranIterations: Integer,
didConverge: Boolean,
createMillis: Integer,
computeMillis: Integer,
postProcessingMillis: Integer,
mutateMillis: Integer,
centralityDistribution: Map,
configuration: Map
Name  Type  Default  Optional  Description 

graphName 
String 

no 
The name of a graph stored in the catalog. 
configuration 
Map 

yes 
Configuration for algorithmspecifics and/or graph filtering. 
Name  Type  Default  Optional  Description 

nodeLabels 
String[] 

yes 
Filter the named graph using the given node labels. 
String[] 

yes 
Filter the named graph using the given relationship types. 

Integer 

yes 
The number of concurrent threads used for running the algorithm. 

mutateProperty 
String 

no 
The node property in the GDS graph to which the score is written. 
Name  Type  Default  Optional  Description 

dampingFactor 
Float 

yes 
The damping factor of the Page Rank calculation. Must be in [0, 1). 
Integer 

yes 
The maximum number of iterations of Page Rank to run. 

Float 

yes 
Minimum change in scores between iterations. If all scores change less than the tolerance value the result is considered stable and the algorithm returns. 

String 

yes 
If set, the values stored at the given property are used as relationship weights during the computation. If not set, the graph is considered unweighted. 

sourceNodes 
List 

yes 
A set of nodes to use for computing Personalized Page Rank. 
Name  Type  Description 

ranIterations 
Integer 
The number of iterations run. 
didConverge 
Boolean 
Indicates if the algorithm converged. 
createMillis 
Integer 
Milliseconds for creating the graph. 
computeMillis 
Integer 
Milliseconds for running the algorithm. 
postProcessingMillis 
Integer 
Milliseconds for computing the 
mutateMillis 
Integer 
Milliseconds for adding properties to the inmemory graph. 
nodePropertiesWritten 
Integer 
The number of properties that were written to the inmemory graph. 
centralityDistribution 
Map 
Map containing min, max, mean as well as p50, p75, p90, p95, p99 and p999 percentile values of centrality values. 
configuration 
Map 
The configuration used for running the algorithm. 
Run PageRank in write mode on a named graph.
CALL gds.pageRank.write(
graphName: String,
configuration: Map
)
YIELD
nodePropertiesWritten: Integer,
ranIterations: Integer,
didConverge: Boolean,
createMillis: Integer,
computeMillis: Integer,
postProcessingMillis: Integer,
writeMillis: Integer,
centralityDistribution: Map,
configuration: Map
Name  Type  Default  Optional  Description 

graphName 
String 

no 
The name of a graph stored in the catalog. 
configuration 
Map 

yes 
Configuration for algorithmspecifics and/or graph filtering. 
Name  Type  Default  Optional  Description 

nodeLabels 
String[] 

yes 
Filter the named graph using the given node labels. 
String[] 

yes 
Filter the named graph using the given relationship types. 

Integer 

yes 
The number of concurrent threads used for running the algorithm. Also provides the default value for 'writeConcurrency'. 

Integer 

yes 
The number of concurrent threads used for writing the result to Neo4j. 

String 

no 
The node property in the Neo4j database to which the score is written. 
Name  Type  Default  Optional  Description 

dampingFactor 
Float 

yes 
The damping factor of the Page Rank calculation. Must be in [0, 1). 
Integer 

yes 
The maximum number of iterations of Page Rank to run. 

Float 

yes 
Minimum change in scores between iterations. If all scores change less than the tolerance value the result is considered stable and the algorithm returns. 

String 

yes 
If set, the values stored at the given property are used as relationship weights during the computation. If not set, the graph is considered unweighted. 

sourceNodes 
List 

yes 
A set of nodes to use for computing Personalized Page Rank. 
Name  Type  Description 

ranIterations 
Integer 
The number of iterations run. 
didConverge 
Boolean 
Indicates if the algorithm converged. 
createMillis 
Integer 
Milliseconds for creating the graph. 
computeMillis 
Integer 
Milliseconds for running the algorithm. 
postProcessingMillis 
Integer 
Milliseconds for computing the 
writeMillis 
Integer 
Milliseconds for writing result data back. 
nodePropertiesWritten 
Integer 
The number of properties that were written to Neo4j. 
centralityDistribution 
Map 
Map containing min, max, mean as well as p50, p75, p90, p95, p99 and p999 percentile values of centrality values. 
configuration 
Map 
The configuration used for running the algorithm. 
It is also possible to execute the algorithm on a graph that is projected in conjunction with the algorithm execution.
In this case, the graph does not have a name, and we call it anonymous.
When executing over an anonymous graph the configuration map contains a graph projection configuration as well as an algorithm
configuration.
All execution modes support execution on anonymous graphs, although we only show syntax and modespecific configuration for
the write
mode for brevity.
For more information on syntax variants, see Section 6.1, “Syntax overview”.
Run PageRank in write mode on an anonymous graph:
CALL gds.pageRank.write(
configuration: Map
)
YIELD
nodePropertiesWritten: Integer,
ranIterations: Integer,
didConverge: Boolean,
createMillis: Integer,
computeMillis: Integer,
writeMillis: Integer,
centralityDistribution: Map,
configuration: Map
Name  Type  Default  Optional  Description 

nodeProjection 
String, String[] or Map 

yes 
The node projection used for anonymous graph creation via a Native projection. 
relationshipProjection 
String, String[] or Map 

yes 
The relationship projection used for anonymous graph creation a Native projection. 
nodeQuery 
String 

yes 
The Cypher query used to select the nodes for anonymous graph creation via a Cypher projection. 
relationshipQuery 
String 

yes 
The Cypher query used to select the relationships for anonymous graph creation via a Cypher projection. 
nodeProperties 
String, String[] or Map 

yes 
The node properties to project during anonymous graph creation. 
relationshipProperties 
String, String[] or Map 

yes 
The relationship properties to project during anonymous graph creation. 
Integer 

yes 
The number of concurrent threads used for running the algorithm. Also provides the default value for 'readConcurrency' and 'writeConcurrency'. 

readConcurrency 
Integer 

yes 
The number of concurrent threads used for creating the graph. 
Integer 

yes 
The number of concurrent threads used for writing the result to Neo4j. 

String 

no 
The node property in the Neo4j database to which the score is written. 
Name  Type  Default  Optional  Description 

dampingFactor 
Float 

yes 
The damping factor of the Page Rank calculation. Must be in [0, 1). 
Integer 

yes 
The maximum number of iterations of Page Rank to run. 

Float 

yes 
Minimum change in scores between iterations. If all scores change less than the tolerance value the result is considered stable and the algorithm returns. 

String 

yes 
If set, the values stored at the given property are used as relationship weights during the computation. If not set, the graph is considered unweighted. 

sourceNodes 
List 

yes 
A set of nodes to use for computing Personalized Page Rank. 
The results are the same as for running write mode with a named graph, see the write mode syntax above.
In this section we will show examples of running the PageRank algorithm on a concrete graph. The intention is to illustrate what the results look like and to provide a guide in how to make use of the algorithm in a real setting. We will do this on a small web network graph of a handful nodes connected in a particular pattern. The example graph looks like this:
The following Cypher statement will create the example graph in the Neo4j database:
CREATE
(home:Page {name:'Home'}),
(about:Page {name:'About'}),
(product:Page {name:'Product'}),
(links:Page {name:'Links'}),
(a:Page {name:'Site A'}),
(b:Page {name:'Site B'}),
(c:Page {name:'Site C'}),
(d:Page {name:'Site D'}),
(home)[:LINKS {weight: 0.2}]>(about),
(home)[:LINKS {weight: 0.2}]>(links),
(home)[:LINKS {weight: 0.6}]>(product),
(about)[:LINKS {weight: 1.0}]>(home),
(product)[:LINKS {weight: 1.0}]>(home),
(a)[:LINKS {weight: 1.0}]>(home),
(b)[:LINKS {weight: 1.0}]>(home),
(c)[:LINKS {weight: 1.0}]>(home),
(d)[:LINKS {weight: 1.0}]>(home),
(links)[:LINKS {weight: 0.8}]>(home),
(links)[:LINKS {weight: 0.05}]>(a),
(links)[:LINKS {weight: 0.05}]>(b),
(links)[:LINKS {weight: 0.05}]>(c),
(links)[:LINKS {weight: 0.05}]>(d);
This graph represents eight pages, linking to one another.
Each relationship has a property called weight
, which describes the importance of the relationship.
In the examples below we will use named graphs and native projections as the norm. However, anonymous graphs and/or Cypher projections can also be used. 
The following statement will create a graph using a native projection and store it in the graph catalog under the name 'myGraph'.
CALL gds.graph.create(
'myGraph',
'Page',
'LINKS',
{
relationshipProperties: 'weight'
}
)
First off, we will estimate the cost of running the algorithm using the estimate
procedure.
This can be done with any execution mode.
We will use the write
mode in this example.
Estimating the algorithm is useful to understand the memory impact that running the algorithm on your graph will have.
When you later actually run the algorithm in one of the execution modes the system will perform an estimation.
If the estimation shows that there is a very high probability of the execution going over its memory limitations, the execution
is prohibited.
To read more about this, see Section 3.1.3, “Automatic estimation and execution blocking”.
For more details on estimate
in general, see Section 3.1, “Memory Estimation”.
The following will estimate the memory requirements for running the algorithm:
CALL gds.pageRank.write.estimate('myGraph', {
writeProperty: 'pageRank',
maxIterations: 20,
dampingFactor: 0.85
})
YIELD nodeCount, relationshipCount, bytesMin, bytesMax, requiredMemory
nodeCount  relationshipCount  bytesMin  bytesMax  requiredMemory 

8 
14 
856 
856 
"856 Bytes" 
In the stream
execution mode, the algorithm returns the score for each node.
This allows us to inspect the results directly or postprocess them in Cypher without any side effects.
For example, we can order the results to find the nodes with the highest PageRank score.
For more details on the stream
mode in general, see Section 3.3.1, “Stream”.
The following will run the algorithm in stream
mode:
CALL gds.pageRank.stream('myGraph')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC, name ASC
name  score 

"Home" 
3.2362018343177623 
"About" 
1.0611098931171001 
"Links" 
1.0611098931171001 
"Product" 
1.0611098931171001 
"Site A" 
0.3292259060894139 
"Site B" 
0.3292259060894139 
"Site C" 
0.3292259060894139 
"Site D" 
0.3292259060894139 
The above query is running the algorithm in stream
mode as unweighted
.
Below is a weighted example
We are using 
In the stats
execution mode, the algorithm returns a single row containing a summary of the algorithm result.
For example PageRank stats returns centrality histogram which can be used to monitor the distribution of PageRank score values
across all computed nodes.
This execution mode does not have any side effects.
It can be useful for evaluating algorithm performance by inspecting the computeMillis
return item.
In the examples below we will omit returning the timings.
The full signature of the procedure can be found in the syntax section.
For more details on the stats
mode in general, see Section 3.3.2, “Stats”.
The following will run the algorithm and returns the result in form of statistical and measurement values.
CALL gds.pageRank.stats('myGraph', {
maxIterations: 20,
dampingFactor: 0.85
})
YIELD centralityDistribution
RETURN centralityDistribution.max AS max
max 

3.236204147338867 
The centrality histogram can be useful for inspecting the computed scores or perform normalizations.
The mutate
execution mode extends the stats
mode with an important side effect: updating the named graph with a new node property containing the score for that node.
The name of the new property is specified using the mandatory configuration parameter mutateProperty
.
The result is a single summary row, similar to stats
, but with some additional metrics.
The mutate
mode is especially useful when multiple algorithms are used in conjunction.
For more details on the mutate
mode in general, see Section 3.3.3, “Mutate”.
The following will run the algorithm in mutate
mode:
CALL gds.pageRank.mutate('myGraph', {
maxIterations: 20,
dampingFactor: 0.85,
mutateProperty: 'pagerank'
})
YIELD nodePropertiesWritten, ranIterations
nodePropertiesWritten  ranIterations 



The write
execution mode extends the stats
mode with an important side effect: writing the score for each node as a property to the Neo4j database.
The name of the new property is specified using the mandatory configuration parameter writeProperty
.
The result is a single summary row, similar to stats
, but with some additional metrics.
The write
mode enables directly persisting the results to the database.
For more details on the write
mode in general, see Section 3.3.4, “Write”.
The following will run the algorithm in write
mode:
CALL gds.pageRank.write('myGraph', {
maxIterations: 20,
dampingFactor: 0.85,
writeProperty: 'pagerank'
})
YIELD nodePropertiesWritten, ranIterations
nodePropertiesWritten  ranIterations 



By default, the algorithm is considering the relationships of the graph to be unweighted
, to change this behaviour we can use configuration parameter called relationshipWeightProperty
.
In the weighted
case, the previous score of a node send to its neighbors, is multiplied by the relationship weight and then divided by the
sum of the weights of its outgoing relationships.
If the value of the relationship property is negative it will be ignored during computation.
Below is an example of running the algorithm using the relationship property.
The following will run the algorithm in stream
mode using relationship weights:
CALL gds.pageRank.stream('myGraph', {
maxIterations: 20,
dampingFactor: 0.85,
relationshipWeightProperty: 'weight'
})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC, name ASC
name  score 

"Home" 
3.5528570797032444 
"Product" 
1.9541302592027932 
"About" 
0.7513767506927252 
"Links" 
0.7513767506927252 
"Site A" 
0.1816736041444528 
"Site B" 
0.1816736041444528 
"Site C" 
0.1816736041444528 
"Site D" 
0.1816736041444528 
We are using 
The tolerance
configuration parameter denotes the minimum change in scores between iterations.
If all scores change less than the configured tolerance
value the result stabilises, and the algorithm returns.
The following will run the algorithm in stream
mode using bigger tolerance
value:
CALL gds.pageRank.stream('myGraph', {
maxIterations: 20,
dampingFactor: 0.85,
tolerance: 0.1
})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC, name ASC
name  score 

"Home" 
2.8504481718642634 
"About" 
0.9325181037187577 
"Links" 
0.9325181037187577 
"Product" 
0.9325181037187577 
"Site A" 
0.30351586283650245 
"Site B" 
0.30351586283650245 
"Site C" 
0.30351586283650245 
"Site D" 
0.30351586283650245 
In this example we are using tolerance: 0.1
, so the results are a bit different compared to the ones from stream example which is using the default value of tolerance
.
Note that the nodes 'About', 'Link' and 'Product' now have the same score, while with the default value of tolerance
the node 'Product' has higher score than the other two.
The damping factor configuration parameter accepts values between 0 (inclusive) and 1 (exclusive). If its value is too high then problems of sinks and spider traps may occur, and the values may oscillate so that the algorithm does not converge. If it’s too low then all scores are pushed towards 1, and the result will not sufficiently reflect the structure of the graph.
The following will run the algorithm in stream
mode using smaller dampingFactor
value:
CALL gds.pageRank.stream('myGraph', {
maxIterations: 20,
dampingFactor: 0.05
})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC, name ASC
name  score 

"Home" 
1.2487309578806898 
"About" 
0.9708121816863439 
"Links" 
0.9708121816863439 
"Product" 
0.9708121816863439 
"Site A" 
0.9597081215046243 
"Site B" 
0.9597081215046243 
"Site C" 
0.9597081215046243 
"Site D" 
0.9597081215046243 
Compared to the results from the stream example which is using the default value of dampingFactor
the score values are closer to each other when using dampingFactor: 0.05
.
Also, note that the nodes 'About', 'Link' and 'Product' now have the same score, while with the default value of dampingFactor
the node 'Product' has higher score than the other two.
Personalized PageRank is a variation of PageRank which is biased towards a set of sourceNodes
.
This variant of PageRank is often used as part of recommender systems.
The following examples show how to run PageRank centered around 'Site A'.
The following will run the algorithm and stream results:
MATCH (siteA:Page {name: 'Site A'})
CALL gds.pageRank.stream('myGraph', {
maxIterations: 20,
dampingFactor: 0.85,
sourceNodes: [siteA]
})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC, name ASC
name  score 

"Home" 
0.4015879064354522 
"Site A" 
0.1690742583792599 
"About" 
0.11305649114656262 
"Links" 
0.11305649114656262 
"Product" 
0.11305649114656262 
"Site B" 
0.019074258379259846 
"Site C" 
0.019074258379259846 
"Site D" 
0.019074258379259846 
Comparing these results to the ones from the stream example (which is not using sourceNodes
configuration parameter) shows that the 'Site A' node that we used in the sourceNodes
list now scores second instead of fourth.