Source: https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/common_neighbors/ Documentation version: v5.3.2 # Common Neighbors ## Algorithm introduction Common neighbors predicts potential links by counting shared neighbors between node pairs. Return the common neighbors of two nodes identified by node property id and the total count. For more information, see [Common Neighbors](https://en.wikipedia.org/wiki/Link_prediction). ## Data model To implement the Common Neighbors algorithm in GQL, the following data model is used to create a graph type: - Entities are represented by nodes of type `Node`, with properties `id` and `rating`. - Relationships are represented by edges of type `Link`, with property `weight`. For the complete definition of the graph type, see [Prepare graph data](https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/common_neighbors/#1_prepare_graph_data). ## Procedure implementation[]() To compute Common Neighbors results, a [procedure](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/procedures/create/) is created. For more information about the procedure, see [Procedure implementation](https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/common_neighbors/#procedure_implement). The following section describes the key components of the procedure and how it works. The procedure takes the following input parameters: - `left_id`: `INT64`. ID of the first node. - `right_id`: `INT64`. ID of the second node. Additionally, the following variables are defined within the procedure: | Variable name | Variable type | Description | `result_neighbors` | Global [SumAgg aggregator value variable](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/variable-definition/agg/sum_agg/) | List of common neighbor node IDs for the queried pair. | `result_count` | Global [SumAgg aggregator value variable](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/variable-definition/agg/sum_agg/) | Count of common neighbors. | `seen_left` | Node-attached [SumAgg aggregator value variable](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/variable-definition/agg/sum_agg/) | Per-node flag: node is adjacent to the left query node. | `seen_right` | Node-attached [SumAgg aggregator value variable](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/variable-definition/agg/sum_agg/) | Per-node flag: node is adjacent to the right query node. The following steps outline the logic of the procedure: 1. For the left node (left_id), traverse all its edges and mark each neighbor with `seen_left`. 2. For the right node (right_id), traverse all its edges and mark each neighbor with `seen_right`. 3. Collect all nodes with both `seen_left` and `seen_right` (excluding left_id and right_id themselves) into `result_neighbors`; count them in `result_count`. 4. Return the list of common neighbor IDs and the total count. ## Steps Run the following code blocks in order in the NebulaGraph Studio CONSOLE. For first-time setup, follow [Prepare algorithm sample data](https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/prepare-data/) to check where to run commands and how the directory is mounted. ### 1. Prepare graph data[]() 1. Create a graph type that matches your data model. ```` ''' CREATE GRAPH TYPE IF NOT EXISTS common_neighbors_graph_type AS { NODE Node (LABEL Node {id INT PRIMARY KEY, rating INT}), EDGE Link (Node)-[LABEL Link {weight INT, MULTIEDGE KEY()}]->(Node) } ''' ```` 2. Download these CSV files and save them with their original names in `examples/algorithms/common_neighbors/` under your deployment directory: - [common_neighbors_node.csv](https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/files/common_neighbors/common_neighbors_node.csv): Node data. - [common_neighbors_edge.csv](https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/files/common_neighbors/common_neighbors_edge.csv): Edge data. Preview the CSV files common_neighbors_node.csv ```` id,rating 1,0 2,2 3,1 4,0 5,0 6,2 7,1 8,2 9,0 10,1 11,0 12,2 13,1 14,1 15,0 16,2 17,0 18,1 19,2 20,0 21,2 22,1 23,0 24,1 ```` common_neighbors_edge.csv ```` src_id,dst_id,weight 1,2,4 1,3,2 1,4,7 1,5,9 2,3,1 2,4,6 2,5,5 2,6,2 3,4,3 3,5,4 3,6,8 4,6,2 4,7,6 4,8,5 5,6,4 5,8,7 5,9,6 6,8,1 6,9,5 6,10,6 7,9,2 7,10,9 8,9,3 8,11,6 8,12,4 9,10,4 9,12,7 9,13,2 10,12,1 10,13,8 10,14,4 11,12,2 11,14,5 11,15,7 12,14,3 12,15,6 12,16,5 13,15,2 13,16,7 14,15,4 14,17,8 14,18,2 15,16,1 15,18,5 15,19,3 16,18,3 16,19,6 17,18,2 17,20,7 17,21,5 18,19,4 18,21,9 18,22,6 19,21,1 19,22,5 20,21,3 20,23,6 20,24,8 21,22,2 21,23,4 21,24,7 22,24,4 23,24,1 ```` 3. Create a temporary graph based on the graph type and load the data files into the temporary graph. ```` CREATE TEMPORARY GRAPH IF NOT EXISTS #common_neighbors_graph TYPED common_neighbors_graph_type ```` ```` ''' USE #common_neighbors_graph IMPORT INTO GRAPH { NODE (v@Node {id: id, rating: rating}) FROM DATAFILE { PATH: "file:///examples/algorithms/common_neighbors/common_neighbors_node.csv", FORMAT: "CSV", DELIMITER: ',' }, EDGE (id: src_id)-[e@Link {weight: weight}]->(id: dst_id) FROM DATAFILE { PATH: "file:///examples/algorithms/common_neighbors/common_neighbors_edge.csv", FORMAT: "CSV", DELIMITER: ',' } } ''' ```` After the import succeeds, run this query in the console to check the node count: ```` ''' USE #common_neighbors_graph MATCH (n) RETURN count(n) AS node_count ''' ```` The expected `node_count` is `24`. If it differs, [check the files and import results](https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/prepare-data/#troubleshooting) before continuing. ### 2. Create a procedure[]() Create a procedure to implement the Common Neighbors algorithm. For more information about the procedure, see [Procedure implementation](https://dev-docs.nebula-graph.io/v5.3.2/analytic/algorithms/common_neighbors/#procedure_implement). ```` ''' CREATE OR REPLACE PROCEDURE common_neighbors(left_id INT64, right_id INT64) RETURNS (neighbor_ids LIST, common_neighbor_count INT64) COMMENT "Return the common neighbors of two vertices identified by vertex property id and the total count." AS { VALUE result_neighbors ListAgg VALUE result_count SumAgg = 0 NODE VALUE seen_left OrAgg = false NODE VALUE seen_right OrAgg = false MATCH (s)-[e]-(n) WHERE s.id = left_id PER PATH { SET n.@seen_left += true } MATCH (s)-[e]-(n) WHERE s.id = right_id PER PATH { SET n.@seen_right += true } MATCH (n) WHERE n.@seen_left = true AND n.@seen_right = true AND n.id <> left_id AND n.id <> right_id PER NODE (n) { SET @result_neighbors += n.id SET @result_count += 1 } RETURN @result_neighbors AS neighbor_ids, @result_count AS common_neighbor_count } ''' ```` ### 3. Call your procedure[]() Find the common neighbors of nodes `6` and `9`, returning their IDs and count. ```` USE #common_neighbors_graph CALL common_neighbors(6, 9) RETURN neighbor_ids, common_neighbor_count ```` Returns: ```` +--------------+-----------------------+ | neighbor_ids | common_neighbor_count | +--------------+-----------------------+ | [5, 10, 8] | 3 | +--------------+-----------------------+ ```` Save results to a file or graph To save the returned results as CSV files or write them to a graph, see [EXPORT](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/in-out/export/). Match the exported fields to the returned columns and target properties.