Creating virtual elements from output of apoc.path.expand

(Mike Oaten) #1

I want to create a virtual relationship from the output of apoc.path.expand. I assumed I could feed in the output to the second part of the query using WITH, but don't know if/how to access graph elements as apoc.path.expand only yields a path? (apologies if I'm missing something obvious).

Thanks in advance

call apoc.path.expand(c, "CONCERNS", "", 0, 6) yield path
MATCH (co:CompanyOfficer)<-[:CONCERNS]-(:Event)-[:CONCERNS]->(c1:Company)
WITH co, c1
CALL apoc.create.vRelationship(c1,'CONNECTED_TO',{}, co) YIELD rel
RETURN co, c1, rel

(Andrew Bowman) #2

Hi Mike,

What are you attempting to get out of the results?

You can use nodes(path) to get a collection of nodes that make up the path (per path), or you can use relationships(path) to get a collection of relationships that make up the path (per path).

If you need just the last node of each path, you can use last(nodes(path)).

(Mike Oaten) #3

Hi Andrew, thanks for stepping in.

The expand query returns this

Pink nodes are companies, yellow company officers. There are connected by intermediate nodes 'Events' which hold properties such as dates. I want to present a virtual graph representation where the intermediate nodes are removed. There is a common relationship type, 'CONCERNS', which connects all nodes in this subgraph.

I can create the desired output structure with this query

MATCH (co:CompanyOfficer {surname: 'OATEN'})<-[:CONCERNS]-(:Event)-[:CONCERNS]->(c:Company)
WITH co, c
CALL apoc.create.vRelationship(c,'CONNECTED_TO',{}, co) YIELD rel
RETURN co, c, rel

Which returns

Just can't do so from the output of apoc.path.expand. I played around with nodes(path) and relationships(path) but no joy.

I am assuming I've got the sequencing right, i.e. produce the subgraph and then 'virtualise' it?


(Mike Oaten) #4

Hi Andrew, forgot to reply to you just posted in the thread... always learning!

(Andrew Bowman) #5

So this is a tad tricky. We need to get ahold of relationships in the path, and from those with the common start node (which will be :Event nodes), gather the distinct end nodes (:CompanyOfficer and :Company nodes), then create the vNodes between those nodes.

If every :Event node only connects a pair of these nodes, this kind of query should work:

call apoc.path.expandConfig(c, {maxLevel:6, relationshipFilter:'CONCERNS', uniqueness:'RELATIONSHIP_GLOBAL'}) YIELD path
UNWIND relationships(path) as rel
WITH startNode(rel) as event, collect(DISTINCT endNode(rel)) as toConnect
WITH toConnect[0] as toConnect1, toConnect[1] as toConnect2
CALL apoc.create.vRelationship(toConnect1,'CONNECTED_TO',{}, toConnect2) YIELD rel
RETURN toConnect1, rel, toConnect2

I'm using expandConfig() here as this adds some additional options, and by using RELATIONSHIP_GLOBAL uniqueness I minimize the number of times each relationship is traversed, then I get the DISTINCT rels so I don't process the same relationship multiple times.

If an :Event node can connect > 2 other nodes, then we'll need to adjust the query to get all possible pairs of toConnect nodes to create the vRelationship between each pair. Let me know if you need an example of that approach.

EDIT: fixed a small error in my query, it was originally collecting startNodes of the relationships, but we want to collect the endNodes instead.

(Mike Oaten) #6

Cheers Andrew, I'll give it a bash

(Mike Oaten) #7

Andrew, yes now works a treat after that edit. Thank you again.