2

How can I create full node tree from existing node tree, Actually i have 1 node and i need to find all relation and nodes that has my existing top node. I need to create full node tree to another node.

Copy All Node Tree from A with Relation and create Duplicate same node and relation for B Node

enter image description here

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
user3714269
  • 129
  • 1
  • 2
  • 4
  • Are you sure the node is the root of a tree? I ask because if not then you need to keep track of visited nodes when duplicating because you could be in a cycle and end up in an infinite loop. – Guy Coder Dec 03 '18 at 15:14
  • Yes , i need to create all relationship and node which already with old node – user3714269 Dec 03 '18 at 15:21
  • APOC has [Clone nodes](https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_clone_nodes). I have never used it but I would try it if I had your problem. – Guy Coder Dec 03 '18 at 15:37
  • Very frustrating , cant find any other way :( – user3714269 Dec 03 '18 at 16:44
  • @user3714269 What about an example? Input data, desired result and your attempt? – stdob-- Dec 03 '18 at 17:39
  • Update pic for more clarity – user3714269 Dec 03 '18 at 21:15
  • Cypher code needed – user3714269 Dec 03 '18 at 22:43
  • 1
    Can you have any unique nodes in the tree (e.g., are there nodes that have property values that are supposed to be unique)? It would not be appropriate (nor even possible, if there are uniqueness constraints) to simply clone unique nodes. – cybersam Dec 03 '18 at 22:58
  • Heads up, I have a PR open for a new APOC Procedure, [apoc.refactor.cloneSubgraph()](https://github.com/neo4j-contrib/neo4j-apoc-procedures/pull/1087), which is aimed at exactly this use case. If there are no issues merging, you can expect this in the next APOC release for Neo4j 3.5 (and possibly 3.4 if we backport it) – InverseFalcon Feb 07 '19 at 10:14
  • @cybersam your comment was really on point. I'm currently facing this exact same problem. What I'm trying to do as a workaround is to create a virtual graph and then iterating through each node and copy it as a vnode. I'm stuck with the relationships because with a simple Match query it's hard to get start and end nodes. – Marcos Sep 27 '22 at 20:04

1 Answers1

3

Okay, this is a tricky one.

As others have mentioned apoc.refactor.cloneNodesWithRelationships() can help, but this will also result in relationships between cloned nodes and the originals, not just the clones, as this proc wasn't written with this kind of use case in mind.

So this requires us to do some Cypher acrobatics to find the relationships from the cloned nodes that don't go to the cloned nodes so we can delete them.

However at the same time we also have to identify the old root node so we can refactor relationships to the new root (this requires separate processing for incoming and outgoing relationships).

Here's a query that should do the trick, making assumptions about the nodes since you didn't provide any details about your graph:

MATCH (a:Root{name:'A'})
WITH a, id(a) as aId
CALL apoc.path.subgraphNodes(a, {}) YIELD node
WITH aId, collect(node) as nodes
CALL apoc.refactor.cloneNodesWithRelationships(nodes) YIELD input, output
WITH aId, collect({input:input, output:output}) as createdData, collect(output) as createdNodes
WITH createdNodes, [item in createdData WHERE item.input = aId | item.output][0] as aClone // clone of root A node
UNWIND createdNodes as created
OPTIONAL MATCH (created)-[r]-(other)
WHERE NOT other in createdNodes
DELETE r // get rid of relationships that aren't between cloned nodes
// now to refactor relationships from aClone to the new B root node
WITH DISTINCT aClone
MATCH (b:Root{name:'B'})
WITH aClone, b
MATCH (aClone)-[r]->()
CALL apoc.refactor.from(r, b) YIELD output
WITH DISTINCT b, aClone
MATCH (aClone)<-[r]-()
CALL apoc.refactor.to(r, b) YIELD output
WITH DISTINCT aClone
DETACH DELETE aClone
InverseFalcon
  • 29,576
  • 4
  • 38
  • 51