Hi @janezic !
Im pretty sure that on your use case the best way to do so is extending APOC in order to create your own procedure able to do that.
Meanwhile, I offer you one option/idea that is half deprecated but It can be easily adjusted.
Using the base graph:
CREATE (rootA:Root{name:'A'}),
(rootB:Root{name:'B'}),
(n1:Node{name:'node1', id:1}),
(n2:Node{name:'node2', id:2}),
(n3:Node{name:'node3', id:3}),
(n4:Node{name:'node4', id:4}),
(n5:Node{name:'node5', id:5}),
(n6:Node{name:'node6', id:6}),
(n7:Node{name:'node7', id:7}),
(n8:Node{name:'node8', id:8}),
(n9:Node{name:'node9', id:9}),
(n10:Node{name:'node10', id:10}),
(n11:Node{name:'node11', id:11}),
(n12:Node{name:'node12', id:12})
CREATE (rootA)-[:LINK]->(n1)-[:LINK]->(n2)-[:LINK]->(n3)-[:LINK]->(n4)
CREATE (n1)-[:LINK]->(n5)-[:LINK]->(n6)<-[:LINK]-(n7)
CREATE (n5)-[:LINK]->(n8)
CREATE (n5)-[:LINK]->(n9)-[:DIFFERENT_LINK]->(n10)
CREATE (rootB)-[:LINK]->(n11);
You can clone part of it with (notice I create a specifix rule to do so)
MATCH (rootA:Root {name:'A'})
WITH rootA
MATCH path = (rootA)-[:LINK*]->(node)
where NONE(n in nodes(path) where n.name = 'node6' or n.name = 'node9')
UNWIND relationShips(path) AS r
WITH collect(path) as paths, collect(DISTINCT endNode(r)) AS endNodes,
collect(DISTINCT startNode(r)) AS startNodes
UNWIND endNodes AS leaf
WITH paths, leaf WHERE NOT leaf IN startNodes
WITH collect(leaf) as leafs, paths
CALL apoc.refactor.cloneSubgraphFromPaths(paths, {})
YIELD input, output
WITH input as inp, output as out, leafs
MATCH (n)
where id(n) = inp
and n in leafs
with n, out
CALL apoc.refactor.cloneNodesWithRelationships([n])
yield input, output
CALL apoc.refactor.mergeNodes([out,output],{
properties:"combine",
mergeRels:false
})
yield node
return input, output,out, node
Lemme know if it's easy to read/useful on your use case.
Bennu