Applying virtual relationships properly

Hi there, I have a graph containing persons who participate in one or more events on the one hand and are involved in in one or more projects on the other hand. The events are linked to objects, the projects to organisations. What I would like is to create a unique virtual relationship between persons and objects and between person and organisations.

MERGE (p1:Person {label:'Person 1'})
MERGE (p2:Person {label:'Person 2'})
MERGE (e1:Event {eventStart:'2023-11-01', label: 'Event 1'})
MERGE (e2:Event {eventStart:'2023-12-02', label: 'Event 2'})
MERGE (e3:Event {eventStart:'2023-11-03', label: 'Event 3'})
MERGE (e4:Event {eventStart:'2023-11-04', label: 'Event 4'})
MERGE (e5:Event {eventStart:'2023-11-05', label: 'Event 5'})
MERGE (r1:Project {label: "Project 1"})
MERGE (r2:Project {label: "Project 2"})
MERGE (r3:Project {label: "Project 3"})
MERGE (o:Organisation {label: "Organisation 1"})
MERGE (o1:Object {label: "Object 1"})
MERGE (o2:Object {label: "Object 2"})
MERGE (o)-[:EXECUTES]-(r1)
MERGE (o)-[:EXECUTES]-(r2)
MERGE (o)-[:EXECUTES]-(r3)					   
MERGE (p1)-[:INVOLVED]-(r1)
MERGE (p2)-[:INVOLVED]-(r2)						 
MERGE (p2)-[:INVOLVED]-(r3)						 
MERGE (p1) -[:PARTICIPATES]->(e1)
MERGE (p1)-[:PARTICIPATES]->(e2)
MERGE (p2)-[:PARTICIPATES]->(e3)
MERGE (p2)-[:PARTICIPATES]->(e4)
MERGE (p1)-[:PARTICIPATES]->(e5)
MERGE (p2)-[:PARTICIPATES]->(e5)							 
MERGE (e1)<-[:REQUIRES]-(o1)
MERGE (e2)<-[:REQUIRES]-(o1)
MERGE (e3)<-[:REQUIRES]-(o2)
MERGE (e4)<-[:REQUIRES]-(o2)
MERGE (e5)<-[:REQUIRES]-(o2)

The graph looks like this:

I have tried to create the desired graph with the following:

MATCH (person:Person) -[:PARTICIPATES]-> (event:Event) <-[:REQUIRES]- (object:Object)
with person,object, count(event) as cntUsed
CALL apoc.create.vRelationship(person,"USED",{number: cntUsed },object) yield rel as vRel1
with person,object,vRel1
MATCH (person)-[:INVOLVED]->(project:Project)<-[:EXECUTES]-(organisation:Organisation)
WITH person,organisation, count(project) as cntInvolved,object,vRel1
CALL apoc.create.vRelationship(person,"KNOWS",{number: cntInvolved },organisation) yield rel as vRel2
RETURN person, object, organisation,vRel1, vRel2

The result is:
example-01-result-01

There are two virtual relationships 'KNOWS' between Person 1 and Organisation 1. This makes sense of course.

How do I 'split' the graph so that I person 1 KNOWS Organisation 1 (through Project 1) and person 2 KNOWS Organisation 1 (through Project 1 and 2)?

Can someone explain and suggest how to modify the Cypher code?

Hi @kees1 !

What about something like this:

MATCH (person:Person) -[:PARTICIPATES]-> (event:Event) <-[:REQUIRES]- (object:Object)
with person,object, count(event) as cntUsed
CALL apoc.create.vRelationship(person,"USED",{number: cntUsed },object) yield rel as vRel1
with person,collect(object) as objects,collect(vRel1) as vrels1
CALL {
    WITH person
    MATCH (person)-[:INVOLVED]->(project:Project)<-[:EXECUTES]-(organisation:Organisation)
    WITH person,organisation, collect(project.label) as         projectsInvolved
    CALL apoc.create.vRelationship(person,"KNOWS",{number: size(projectsInvolved), projects: projectsInvolved },organisation) yield rel as vRel2
    return collect(organisation) as organisations, collect(vRel2) as vrels2
}
RETURN person, objects, organisations,vrels1, vrels2
1 Like

Hi Harold,

Thanks for your response and answer. It works like a charm!

Best, Kees