Copy an existing graph with new node labels and new relationship type


I have a graph that I need to copy as is but rename the node labels and the relationship types in the duplicated graph.
What is the neo4j recommended way of doing this?


You can use CYPHER to refactor a graph database.

If you need a new graph database that is a copy of the old one (no need to keep them in sync henceforth) you can do the following:

  • Shut down Neo4j.
  • Take a copy of the existing graph.db in $NEO4J_HOME/data/databases.
  • Set the new copy as the active database in neo4j.conf (or using Neo4j desktop).
  • Start Neo4j.
  • Run CYPHER queries to refactor. For every xyz_event add a new abc_event label. Depending on the size of the database you may need to do this in batches.
  • Run a query to remove the old labels.

Thanks for the reply.
However, I am trying to do this in real time and in the same database.

@dmellonielet Sorry, I misread your intention when said 'copy'. Perhaps you can use:

APOC . also has some clone procedures and then you can use apoc.refactor.setType and similar procedures to update your data.

Hi Michael,

Thank you for the reply. I did explore APOC and it looks very powerful. However, I have an issue with renaming the labels and relationship types. My APOC query looks like this:

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

If I try to call a procedure to rename the label: call apoc.refactor.rename.label('xyz_content', 'abc_content') within the above query, it gives me an error:

Neo.ClientError.Statement.SyntaxError: Procedure call inside a query does not support naming results implicitly (name explicitly using YIELD instead) (line 4, column 1 (offset: 111)) "call apoc.refactor.rename.label('xyz_content', 'abc_content') " ^

Can I use the procedures to rename labels and relationship types within the same above query? If so how? I could not find any good examples of this.

Hi @dmellonielet,

The specific error you are seeing using apoc.refactor.rename.label is because it expects you to YIELD something, so the command should be e.g.

CALL apoc.refactor.rename.label("xyz_assets","abc_assets", nodes) YIELD errorMessages

The list of things you can YIELD can be found by e.g. call"rename.label")

There are a couple of other challenges here

  1. The output of ..cloneSubgraphFromPaths will only give you node information (so if you are wanting to change the relationship labels too you'll need to query again).

  2. Because you have multiple labels that you are trying to change you would need to run the ..rename.labels multiple times

An example is of a second query that could do this is:

MATCH (rootB:abc_event{id: 'e101'})
MATCH (rootB)-[r*]->(node)
// get distinct nodes
with collect(distinct node) as nodes, r
CALL apoc.refactor.rename.label("xyz_assets","abc_assets", nodes) YIELD errorMessages as labelErrors1
CALL apoc.refactor.rename.label("xyz_content","abc_content", nodes) YIELD errorMessages as labelErrors2
//get distinct rels
with r, nodes
unwind r as rel
with collect(distinct rel) as rels
CALL apoc.refactor.rename.type("xyz_event_has_xyc_content","abc_event_has_abc_content", rels) YIELD errorMessages as relErrors1
CALL apoc.refactor.rename.type("xyz_content_has_xyc_media","abc_content_has_abc_media", rels) YIELD errorMessages as relErrors2
return rels