Chapter 24 · Graph Algorithms: Centrality, Community Detection, Similarity, Paths, and Topology Analytics
Node Similarity, KNN, Jaccard/Overlap/Cosine Concepts, and Candidate Generation
Use Node Similarity and KNN for AtlasMart candidate generation, manually validate Jaccard/Overlap/Cosine semantics, and separate structural association from causal recommendation claims.
Learning outcomes
Distinguish structural Node Similarity from property-vector KNN candidate generation.
Compute Jaccard and Overlap manually on a tiny AtlasMart customer-product bipartite fixture.
Explain when Cosine applies to weighted neighborhoods versus KNN float-vector properties.
Bound candidate generation with topK/filtering and validate candidates against business rules and holdout judgments.
Prevent similarity scores from being presented as causal evidence or guaranteed recommendation quality.
1. AtlasMart problem: “similar customer” can mean shared neighbors or similar features
AtlasMart recommendation engineers ask for similar customers. In graph analytics, that phrase can mean two different mechanisms. Node Similarity compares overlap in outgoing neighborhoods in a bipartite graph. KNN compares configured node properties such as numeric vectors and uses approximate neighbor search machinery. They can both produce candidate pairs, but their evidence is different.
| Dimension | Chapter 24 reproducible assumption |
|---|---|
| Neo4j |
2026.07.1 Community, disposable local/container
deployment; database neo4j.
|
| Cypher | Cypher 25 for course examples; Cypher 5 differences are not needed for the GDS procedures used here. |
| Java | Java 21/25 supported by the 2026 line; container image supplies the runtime. |
| Auth/TLS |
User neo4j, password
atlasmart-course-2026; loopback Bolt without
TLS only for this isolated lab.
|
| Driver | No application driver is required for mandatory GDS procedure labs; cypher-shell/Browser is sufficient. |
| GDS | GDS Community 2026.07.0. Community includes all algorithms; maximum GDS concurrency is four CPU cores. |
| APOC | Not required. |
| Graph scope |
Only identifiers prefixed CH24- plus named
in-memory projections beginning
atlas-ch24- are created.
|
| Runtime evidence | This artifact does not execute Neo4j/GDS. Exact fixture counts and hand calculations are deterministic; timings, memory estimates, and algorithm scores must be measured locally. |
// Run in the disposable atlasmart-gds lab from Chapter 23.
RETURN gds.version() AS gdsVersion;
CALL dbms.components() YIELD name, versions, edition
RETURN name, versions, edition;
// Defensive cleanup of Chapter 24 projections if rerunning.
CALL gds.graph.list()
YIELD graphName
WITH graphName WHERE graphName STARTS WITH 'atlas-ch24-'
CALL gds.graph.drop(graphName) YIELD graphName AS dropped
RETURN dropped;
2. Structural versus property-based similarity
| Method | Input evidence | Typical metric | Interpretation |
|---|---|---|---|
| Node Similarity | Outgoing neighbor sets/weighted neighbor lists | JACCARD, OVERLAP, COSINE | Structural equivalence: two source nodes connect to similar targets. |
| KNN | Projected scalar/list node properties | COSINE, EUCLIDEAN, PEARSON, JACCARD/OVERLAP depending property type | Property-space proximity; topology matters only if encoded into the properties. |
| gds.similarity.* functions | Two supplied lists/vectors | Jaccard, overlap, cosine, etc. | Point calculation, not a graph-wide candidate algorithm. |
Using the same word “cosine” does not make two experiments equivalent. In Node Similarity, cosine may be applied to weighted neighbor vectors; in KNN, cosine can compare a list-of-float property such as a deterministic feature vector.
3. Build a customer-view bipartite graph with a manual baseline
UNWIND [
['CH24-SIM-C1','Ada'], ['CH24-SIM-C2','Ben'], ['CH24-SIM-C3','Cy']
] AS row
CREATE (:Customer:CH24SimilarityCustomer {customerId:row[0], name:row[1], chapter24:true});
UNWIND range(1,4) AS i
CREATE (:Product:CH24SimilarityProduct {
productId:'CH24-SIM-P' + toString(i),
name:'Similarity Product ' + toString(i),
featureVec: CASE i
WHEN 1 THEN [1.0,0.0,0.1]
WHEN 2 THEN [0.9,0.1,0.1]
WHEN 3 THEN [0.1,0.9,0.2]
ELSE [0.0,1.0,0.3] END,
chapter24:true
});
MATCH (c1:Customer {customerId:'CH24-SIM-C1'}),
(c2:Customer {customerId:'CH24-SIM-C2'}),
(c3:Customer {customerId:'CH24-SIM-C3'}),
(p1:Product {productId:'CH24-SIM-P1'}),
(p2:Product {productId:'CH24-SIM-P2'}),
(p3:Product {productId:'CH24-SIM-P3'}),
(p4:Product {productId:'CH24-SIM-P4'})
CREATE (c1)-[:VIEWED]->(p1), (c1)-[:VIEWED]->(p2), (c1)-[:VIEWED]->(p3),
(c2)-[:VIEWED]->(p1), (c2)-[:VIEWED]->(p2),
(c3)-[:VIEWED]->(p3), (c3)-[:VIEWED]->(p4);
RETURN 'C1/C2 Jaccard = 2/3; C1/C3 Jaccard = 1/4' AS manualBaseline;
The manual Jaccard calculation is deterministic: C1 and C2 share P1/P2, so intersection size is 2 and union size is 3. C1 and C3 share only P3 and their union is four products, so Jaccard is 1/4.
4. Node Similarity: neighborhood overlap is the data
CALL gds.graph.project(
'atlas-ch24-similarity',
['CH24SimilarityCustomer','CH24SimilarityProduct'],
'VIEWED'
) YIELD graphName, nodeCount, relationshipCount;
CALL gds.nodeSimilarity.stream.estimate('atlas-ch24-similarity', {
similarityMetric:'JACCARD', topK:2, concurrency:2
}) YIELD nodeCount, relationshipCount, requiredMemory
RETURN *;
CALL gds.nodeSimilarity.stream('atlas-ch24-similarity', {
similarityMetric:'JACCARD',
similarityCutoff:0.0,
topK:2,
concurrency:2
}) YIELD node1, node2, similarity
WITH gds.util.asNode(node1) AS a, gds.util.asNode(node2) AS b, similarity
WHERE a:Customer AND b:Customer
RETURN a.customerId AS customer1, b.customerId AS customer2, similarity
ORDER BY customer1, similarity DESC;
Current Node Similarity computes pairwise structural
similarity and can be expensive; topK bounds
returned results/memory but does not magically remove all
computation. Estimate and constrain the source graph.
5. Jaccard, Overlap, and Cosine answer different normalization questions
| Metric | Hand formula intuition | When it can mislead |
|---|---|---|
| Jaccard | |A∩B| / |A∪B| | Penalizes extra neighbors; two sparse users may look very similar from one accidental overlap. |
| Overlap | |A∩B| / min(|A|,|B|) | Returns 1 when the smaller set is contained in the larger; can overstate similarity when activity levels differ greatly. |
| Cosine | dot(A,B) / (||A||·||B||) | Useful for non-negative weighted neighbor vectors or float features, but depends strongly on weight construction. |
UNWIND ['JACCARD','OVERLAP','COSINE'] AS metric
CALL gds.nodeSimilarity.stats('atlas-ch24-similarity', {
similarityMetric:metric,
topK:2,
concurrency:2
})
YIELD nodesCompared, similarityDistribution
RETURN metric, nodesCompared, similarityDistribution;
6. KNN: candidate generation from projected properties
KNN is not a replacement for vector indexes from Chapter 22; here it is a GDS algorithm over projected properties. The first-neighbor sampling and iterative candidate refinement make KNN approximate. Treat recall against a small exact baseline as evidence, not the returned score alone.
CALL gds.graph.project(
'atlas-ch24-knn',
{CH24SimilarityProduct:{properties:['featureVec']}},
'*'
) YIELD graphName, nodeCount, relationshipCount;
CALL gds.knn.stream('atlas-ch24-knn', {
nodeProperties:[{featureVec:'COSINE'}],
topK:2,
randomSeed:24,
concurrency:2
})
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).productId AS product1,
gds.util.asNode(node2).productId AS product2,
similarity
ORDER BY product1, similarity DESC;
Only compare results for the intended
CH24-SIM- products. If other Product nodes are
still present, the projection is too broad for the lab; filter
it or reset first.
7. Deliberately wrong: similarity means “users will buy the same thing”
Structural similarity is association in the selected graph. It can be confounded by popularity, sparse activity, campaign exposure, geography, or data collection. The repair is a candidate pipeline: generate candidates, apply eligibility/business/security filters, rank with separate features, then evaluate against future or held-out outcomes. Similarity is one feature, not a causal claim.
Production judgment and bridge
| Decision | Evidence |
|---|---|
| Structural or feature similarity? | State whether neighbor overlap or property-space distance is the actual signal. |
| Metric | Manual fixture plus domain argument for Jaccard/Overlap/Cosine/other metric. |
| Candidate bounds | topK/cutoffs/source filters and measured candidate volume. |
| Approximation | For KNN, compare recall@k against an exact baseline on a small representative set. |
| Business effect | Offline judgments + controlled online evaluation; never infer causation from graph similarity alone. |
| Security | Ensure candidate generation does not cross tenant/data-access boundaries. |
Next, the output is no longer a score or pair but a route/reachability structure. Path algorithms make weight semantics even stricter because “cost” must compose along a path.
Check your understanding
- What does Node Similarity compare?
- What is the manual Jaccard similarity of C1={P1,P2,P3} and C2={P1,P2}?
- Why can Overlap be 1 when Jaccard is below 1?
- Why is KNN approximate?
- What does a similarity score prove about causation?
Review the answers
1. Outgoing neighborhoods in the projected graph; it measures structural equivalence.
2. 2/3 because the intersection has 2 and the union has 3.
3. If the smaller neighbor set is completely contained in the larger, overlap divides by the smaller-set size while Jaccard divides by the union.
4. It begins with sampled neighbors and iteratively refines candidate neighborhoods rather than exhaustively comparing every pair.
5. Nothing. It is association under a defined graph/property representation and metric.
// Drop all Chapter 24 in-memory projections first.
CALL gds.graph.list()
YIELD graphName
WITH graphName WHERE graphName STARTS WITH 'atlas-ch24-'
CALL gds.graph.drop(graphName) YIELD graphName AS dropped
RETURN dropped;
// Then delete only synthetic Chapter 24 persisted fixtures.
MATCH (n)
WHERE n.chapter24 = true
DETACH DELETE n;
MATCH (n) WHERE n.chapter24 IS NOT NULL REMOVE n.chapter24;
RETURN 'Chapter 24 reset complete' AS status;
Summary and next step
Node Similarity, KNN, Jaccard/Overlap/Cosine Concepts, and Candidate Generation is useful only when its assumptions and observed evidence stay attached to the decision. The examples above establish a reproducible mechanism and boundary; they do not turn one lab result into a universal production rule.
Next, continue to Pathfinding and Spanning/Reachability Algorithms: When GDS Beats Transactional Cypher. Carry forward the verified assumptions, fixture state, version/edition boundaries, and measurements from this lesson instead of treating the next topic as an isolated recipe.
Authoritative references
- GDS Manual v2026.07 — Current Graph Data Science manual and release baseline.
- GDS supported Neo4j versions — Compatibility matrix mapping Neo4j 2026.07 to GDS 2026.07.
- GDS editions — Community includes all algorithms but caps concurrency at four CPU cores and the model catalog at three models; Enterprise adds operational capabilities.
- Algorithm syntax and execution modes — stream/stats/mutate/write/estimate semantics and common algorithm configuration.
- Memory estimation — Estimate memory before allocating algorithm working state.
- Centrality algorithms — Current centrality family and quality tiers.
- Degree Centrality — Degree semantics and weighted/directed behavior.
- PageRank — PageRank iteration, damping, weights, and execution modes.
- Betweenness Centrality — Exact/sampled betweenness, samplingSize/samplingSeed, memory and concurrency tradeoffs.
- Eigenvector Centrality — Transitive influence and power-iteration semantics.
- Louvain — Modularity, levels, tolerance, seeding and execution modes.
- Leiden — Community detection with gamma, theta, randomSeed and connectivity refinement.
- Label Propagation — Fast topology-driven community detection, optional weights and seeds.
- Node Similarity — Structural neighborhood similarity with Jaccard, Overlap, or Cosine.
- K-Nearest Neighbors — Property-based approximate KNN and supported metrics.
- Path finding algorithms — Current shortest path, traversal, spanning, and flow families.
- Dijkstra Source-Target — Positive-cost shortest path semantics; sourceNode/targetNodes current syntax.
- Breadth First Search — Reachability traversal, targets, maxDepth, and stream/mutate modes.
- Graph algorithm operations reference — Current procedure/function names including spanningTree and similarity functions.
- Neo4j current versions — Current Neo4j database release and 5.26 LTS line.