Need help using data from an adjacency matrix to create a graph database in Neo4j?

I'm building a network database for current and future students in a class of mine and wanted to use Neo4j to create a visual graph database that can be later transformed into a Network for students to connect.

I have data/ an adjacency matrix that I want to import into Neo4j to create the relationships between the students and all the classes they share.

Im quite unsure if Neo4j can even support what i'm trying to do but I want to give it a try. Any help?

I helped someone do something similar in a past post. It was a little complicated. Do you have a concrete example?

Hi!

Here is the adjanceny matrix data I want to import into Neo4j but am quite confused how (New User). I am trying to create a visualization of the adjacency matrix in neo4j to sort of present the Network of students without having to create an individual node for each student if that makes sense?

Here is what I'm trying to recreate in Neo4j. I was able to code it in Python but wanted a database like Neo4j so I will be able to integrate it with individuals in charge of front end engineering.

To explain the recent screenshot of the graph. Each node represents a student and the relationships they share depend on if they share a class together( data I will get from the adjacency matrix). The center node would be the student using the database for themselves

Confirm if my understanding is correct. We have N students and an NxN adjacency matrix. Each column represents a single student and each row represents the same student in the same column position. An entry of '1' in the matrix means the two students that intersect the entry are related. I assume the matrix and its transpose are identical, as when student A is related to student B, then student B is also related to student A.

BTW- neo4j is a directed graph database, meaning that every relationship has a direction. Since your student relationships are symmetrically, you don't care about direction. Even so, you will need to specify a direction. I would not add relationships in both directions between two students. It is not necessary, as you can query without constraining to a specific direction.

You goal is to add relationships between the users based on the adjacency matrix.

Does this sound correct?

Yes. This is exactly what I am trying to achieve using Neo4j!!

Ok, here is an example of an approach. The code has two queries. One to create the nodes and one to create the relationships. The semicolon breaks them into two separate queries.

load csv from "file:///AdjacencyMatrix.csv" as row
with row limit 1
unwind row as name
merge(x:Person{name: name});

load csv from "file:///AdjacencyMatrix.csv" as row
with row as names limit 1
load csv from "file:///AdjacencyMatrix.csv" as row
with row, names, size(names)-1 as maxIndex
skip 1
with collect(row) as matrixRows, names, maxIndex
unwind range(0, maxIndex) as i
unwind range(i, maxIndex) as j
match(n:Person{name: names[i]})
match(m:Person{name: names[j]})
forEach(_ in CASE WHEN matrixRows[i][j]="1" THEN [1] ELSE [] END |
    merge(n)-[:RELATED_TO]->(m)
);

I assumed an adjacency matrix that was equal to its transpose, so I only processed the values above the diagonal line (inclusive). You can change this if you want to the relationships in both directions. One use case would be if the value in the matrix represented a relationship property for a relationships from the person on the row to the person on the column.

Screen Shot 2024-03-21 at 10.19.13 AM

The following is the same query using a subquery to implement the conditional logic to only create relationships where the matrix value is "1". This is instead of the forEach loop.

load csv from "file:///AdjacencyMatrix.csv" as row
with row limit 1
unwind row as name
merge(x:Person{name: name});

load csv from "file:///AdjacencyMatrix.csv" as row
with row as names limit 1
load csv from "file:///AdjacencyMatrix.csv" as row
with row, names, size(names)-1 as maxIndex
skip 1
with collect(row) as matrixRows, names, maxIndex
unwind range(0, maxIndex) as i
unwind range(i, maxIndex) as j
call {
    with i, j, matrixRows, names
    with i, j, matrixRows, names
    where matrixRows[i][j]="1"
    match(n:Person{name: names[i]})
    match(m:Person{name: names[j]})
    merge(n)-[:RELATED_TO]->(m)
};