Create relationship between nodes in neo4j - neo4j

In Neo4j, I want to create relationship between nodes where both the nodes are related with a common node.
For Example, I have three nodes where 2 student nodes and a teacher node. I already have relation between student and teacher. Now I want to create a third relationship between student to student where both the students are already related to the same teacher.
In the above image T1 and T2 are teacher nodes. S1, S2, S3 and S4 are student nodes. The relationships which are in blue is already created. now I want to create the relationships which are given in yellow.
Please help. Thanks in Advance.

1) If simple:
// Choose a pair of students with common teacher
MATCH p = (S1:Student)-[:has_teacher]->(T:Teacher)<-[:has_teacher]-(S2:Student)
// Without [:common_teacher] relationships
WHERE NOT (S1)-[:common_teacher]-(S2)
// And create relationships
CREATE (S1)-[r1:common_teacher]->(S2)
CREATE (S2)-[r2:common_teacher]->(S1)
2) If on the other:
You do not need to create additional relationships between the students, because they are already bound by a common teacher.

Related

what is best way to design neo4j graph when relation also have some information to be node

Suppose we have person entity and trip relation to destination entity like city , and we wanna add 3 or 4 kind of information like transportation( type , ticket number , date , .. ) ,that must be node as itself to this relation ..
The question is how we can graph this?
It is not possible to have more than 2 nodes connected to a single relationship.
However, as a workaround, you can "reify" a relationship type as a node label, and create extra relationship types to connect to that new label.
For example, if your current data model is as follows:
(p:Person)-[:TRIP_TO]->(c:City), (transp:Transporation)
and you want to also associate each TRIP_TO relationship with a Transportation node, you can reify the TRIP_TO relationship by replacing -[:TRIP_TO]-> with -[:TAKES]->(trip:Trip)-[:TO]->, like so:
(p)-[:TAKES]->(trip:Trip)-[:TO]->(c)
and adding another new relationship type to connect the Trip node to the appropriate Transportation node:
(trip)-[:USES]->(transp)

counting number of employees connected to other nodes throw multiple relationship

I have some employees who have conflict in positions, depending on their contract they are working as Labors but in the field they are working as drivers, in my database I am recording every position source as relationship between an employ node and role node. what I am trying to figure out is, how should I query the count of employ with no conflict between both relationship, and if there is conflict I want to count the employees distinctly depending on the role of each relationship, for example:
I have the following:
3 employee have driver contract and working as drivers, so their both relationship connected to the driver node.
4 employee have labor contract and working as drivers, so one relationship connect to the labor node and the other connected to driver node.
10 employee have labor contract and working as labor, so their both relationship connected to the labor node.
Look at the model here
MATCH (m2)<-[r2 {source:"operation"}]-(e:Employee)-[r1 {source:"contract"}]->(m1) RETURN distinct m1.name as contract_position, m2.name as operation_position, count(e)
I tried this and it did almost what I want but if I had more than two relationship (more than two sources), I don't think it will work.
keep in mind that I have more roles than theses two roles and I would like to get a nice understanding between what in paper and what in operation.
PS: I am just starting to learn about graph databases and neo4j, so give some slack :)

One to many network graph

I have a dataset of teachers and students. Each teacher is related to 4 or 5 students but there is no relationship between teachers. I made a nodes and edges file (CSV).
I want to make a network graph in circular format where teachers are along the circumference and students in the center of the circle. And relationship is shown by lines/edges from teachers to students. How to do that in Gephi? I am completely clueless.
Nodes : T1,T2,S1,S2,S3,S4,S5 (T stands for teacher and S for student)
Edges : T1-S1,T1-S3,T1-S4,T2-S1,T2-S5,T2-S4

Relating an entity to a relationship proper in Neo4j?

I'm attempting to use Neo4j to model the relationship between projects, staff, and project roles. Each project has a role called "project manager" and a role called "director". What I'm trying to accomplish in the data model is the ability to say "for project A, the director is staff X." For my purposes, it's important that "project", "staff", and "role" are all entities (as opposed to properties). Is this possible in Neo4j? In simpler terms, are associative entities possible in Neo4j? In MySQL, this would be represented with a junction table with a unique id column and three foreign key columns, one for project, staff, and role respectively, which would allow me to identify the relationship between those entities as an entity itself. Thoughts?
#wassgren's answer is a solid one, worth considering.
I'll offer one additional option. That is, you can "Reify" that relationship. Reificiation is sort of when you take a relationship and turn it into a node. You're taking an abstract association (relationship between staff and project) and your'e turning it into a concrete entity (a Role) All of the other answer options involve basically two nodes Project and Staff, with variations on relationships between them. These approaches do not reify role, but store it as a property, or a label, of a relationship.
(director:Staff {name: "Joe"})-[:plays]->(r:Role {label:"Director"})-[:member_of]->(p:Project { name: "Project X"});
So...people don't contribute to projects directly, roles do. And people play roles. Which makes an intuitive sense.
The advantages of this approach is that you get to treat the "Role" as a first-class citizen, and assert relationships and properties about it. If you don't split the "Role" out into a separate node, you won't be able to hang relationships off of the node. Further, if you add extra properties to a relationship that is masquerading as a role, you might end up with confusions about when a property applies to the role, and when it applies to the association between a staff member and a project.
Want to know who is on a project? That's just:
MATCH (p:Project {label: "Project X"})<-[:member_of]-(r:Role)<-[:plays]-(s:Staff)
RETURN s;
So I think what I'm suggesting is more flexible for the long term, but it might also be overkill for you.
Consider a hypothetical future requirement: we want to associate roles with a technical level or job category. I.e. the project manager should always be a VP or higher (silly example). If your role is a relationship, you can't do that. If your role is a proper node, you can.
Conceptually, a Neo4j graph is built based on two main types - nodes and relationships. Nodes can be connected with relationships. However, both nodes and relationships can have properties.
To connect the Project and Staff nodes, the following Cypher statement can be used:
CREATE (p:Project {name:"Project X"})-[:IS_DIRECTOR]->(director:Staff {firstName:"Jane"})
This creates two nodes. The project node has a Label of type Project and the staff node has a Label of type Staff. Between these node there is a relationhip of type IS_DIRECTOR which indicates that Jane is the director of the project. Note that a relationship is always directed.
So, to find all directors of all project the following can be used:
MATCH (p:Project)-[:IS_DIRECTOR]->(director:Staff) RETURN director
The other approach is to add properties to a more general relationship type:
create (p:Project {name:"Project X"})<-[:MEMBER_OF {role:"Director"}]-(director:Staff {firstName:"Jane"})
This shows how you can add properties to a relationship. Notice that the direction of the relationship was changed for the second example.
To find all directors using the property based relationship the following can be used:
MATCH (p:Project)<-[:MEMBER_OF {role:"Director"}]-(directors:Staff) RETURN directors
To retrieve all role types (e.g. director) the following can be used:
MATCH
(p:Project)-[r]->(s:Staff)
RETURN
r, // The actual relationship
type(r), // The relationship type e.g. IS_DIRECTOR
r.role // If properties are available they can be accessed like this
And, to get a unique list of role names COLLECT and DISTINCT can be used:
MATCH
(p:Project)-[r]->(s:Staff)
RETURN
COLLECT(DISTINCT type(r)) // Distinct types
Or, for properties on the relationship:
MATCH
(p:Project)-[r]->(s:Staff)
RETURN
COLLECT(DISTINCT r.role) // The "role" property if that is used
The COLLECT returns a list result and the DISTINCT keyword makes sure that there are no duplicates in the list.

Relations to relation neo4j

Maybe it is a long shot but worth trying...
I have the following relation User1-[:MATCHED]-User2, I want to allow other users to give feedback (Like) on that relation, I am guessing that the obvious answer is to define new node from type Match which will be created for every two matched users and then relate to that node with LIKE relation from each user who liked the match.
I am trying to think about other way to model that in the graph without the overhead of creating new node for each match...
Can a relation relate to other nodes except the start/end nodes?
Any help will be appreciated thanks.
Neo4j does not support hypergraphs or relationships to relationships. Modelling your MATCHED relationship with a node is probably the way to go.
An alternative is to reference the relationship id from another node:
User1-[MATCHED]->User2 (where MATCHED has the id xyz)
User3-[LIKES]->Relationship(relId = xyz)
The "Relationship" node would contain the id of the MATCHED relationship as a property. This relId property would need to be indexed to find all LIKES of a given MATCHED relationship.
This solution is not well suited for traversals though.

Resources