4

I am trying to simulate a file system using Neo4j, Cypher, and Python(Py2Neo).

I have created the data model as shown in the following screenshot.

Type=0 means folder and type=1 means file.

. enter image description here .

I am implementing functions like Copy, Move etc for files/folders.

Move functions look simple, I can create a new relationship and delete the old one. But copying files/folders need to copy the sub-graph.

How can I copy the sub-graph?

I am creating a python module so trying to avoid apoc.

Rajendra Kadam
  • 4,004
  • 1
  • 10
  • 24

1 Answers1

5

Even though you're trying to avoid APOC, it already has this feature implemented in the most recent release: apoc.refactor.cloneSubgraph()

For a non-APOC approach you'll need to accomplish the following:

  1. MATCH to distinct nodes and relationships that make up the subgraph you want to clone. Having a separate list for each will make this easier to process.

  2. Clone the nodes, and get a way to map from the original node to the cloned node.

  3. Process the relationships, finding the start and end nodes, and following the mapping to the cloned nodes, then create the same relationship type using the cloned nodes for your start and end nodes of the relationship, then copy properties from the original relationship. This way you don't have any relationships to the originals, just the clones.

  4. Determine which nodes you want to reanchor (you probably don't want to clone the original), and for any relationship that goes to/from this node, create it (via step 3) to the node you want to use as the new anchor (for example, the new :File which should be the parent of the cloned directory tree).

All this is tough to do in Cypher (steps 3 and 4 in particular), thus the reason all this was encapsulated in apoc.refactor.cloneSubgraph().

InverseFalcon
  • 29,576
  • 4
  • 38
  • 51
  • APOC cloneSubgraph is a good feature. However, one problem I encountered was if I want to copy these subgraph and rename the labels and relationship types, can I do that? – Nicole Aug 27 '19 at 18:39
  • 1
    You can, but it takes a bit of extra work after the call. The procedure YIELDs `input, output, error`, so if you `collect(output)` that will get you all the cloned nodes. You can then apply whatever processing you need to filter to nodes of particular labels and remove the label and set the new one. The relationships will be easier, but you will need to get all the relationships between the cloned nodes and then filter. You can do this with `apoc.algo.cover()` passing the list of all cloned nodes, then filter the resulting relationships, then use `apoc.refactor.setType()` to change their type. – InverseFalcon Aug 27 '19 at 20:47
  • So If my query is: MATCH (rootA:xyz_event{id:'e101'}), (rootB:abc_event{id: 'e101'}) MATCH path = (rootA)-[*]->(node) WITH rootA, rootB, collect(path) as paths CALL apoc.refactor.cloneSubgraphFromPaths(paths, {standinNodes:[[rootA, rootB]]}) YIELD input, output, error RETURN input, output, error Where and how do I collect output and apply refactor for labels and relationship types? Can I do this in the same query? – Nicole Aug 29 '19 at 02:39
  • 4
    You can, you'll want to work with the YIELDed `output` variable from the call, collecting it and working with it to do what you want. For example, you might have `WITH collect(output) as nodes` and then use [list comprehension](https://neo4j.com/docs/cypher-manual/current/syntax/lists/#cypher-list-comprehension) to filter to those with the labels in question then use a FOREACH to remove the old label and add the new label. I already mentioned an approach for relationships using `apoc.algo.cover()`. – InverseFalcon Aug 30 '19 at 21:35
  • Hi @InverseFalcon I'm facing a similar problem but the nodes that needs to be cloned have a UNIQUE constraint on their 'primary key' so they won't be cloned because the label renaming must be done prior to the cloning. Any tip? – Marcos Sep 27 '22 at 12:52
  • @Marcos You may need to temporarily change the labels of the nodes to be cloned to other labels (such that the nodes are not subject to a unique constraint), clone afterwards, then when you're all done, change back the labels on those nodes. – InverseFalcon Sep 28 '22 at 22:25
  • I was planning on using virtual graph but I'm not really sure. – Marcos Sep 29 '22 at 21:57
  • the thing is if I change the labels to do that the nodes won't be queryable – Marcos Sep 29 '22 at 21:58