Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating Neo4j/Cypher relationships dynamically with variable MATCH label

Tags:

neo4j

I need to create relationships between existing nodes and have tried following the youtube on creating dynamic nodes and relationships: https://www.youtube.com/watch?v=KsAb8QHClNg a couple of times but I don't think they cover my use case.

Example Data:

SOURCE  TARGET  LABEL   TYPE    SOURCE_TYPE TARGET_TYPE SOURCE_KEY  TARGET_KEY  PHLEVEL COLOR   SIZE    SCOPE
16      1   ERKRS_ROOT  DIRECTED    ERKRS   ROOT    ERKRS_R300  ROOT_EC3_800    0       #808080 1   FALSE
12      1   ERKRS_ROOT  DIRECTED    ERKRS   ROOT    ERKRS_INT1  ROOT_EC3_800    0       #808080 1   FALSE
51      1   KKBER_ROOT  DIRECTED    KKBER   ROOT    KKBER_GVK1  ROOT_EC3_800    0       #808080 1   FALSE
31      1   KKBER_ROOT  DIRECTED    KKBER   ROOT    KKBER_6000  ROOT_EC3_800    0       #808080 1   FALSE
71      1   FIKRS_ROOT  DIRECTED    FIKRS   ROOT    FIKRS_1000  ROOT_EC3_800    0       #808080 1   FALSE
334     9   KOKRS_ERKRS DIRECTED    KOKRS   ERKRS   KOKRS_2000  ERKRS_IDEA      1       #808080 1   FALSE
335     9   KOKRS_ERKRS DIRECTED    KOKRS   ERKRS   KOKRS_2200  ERKRS_IDEA      1       #808080 1   FALSE
342     9   KOKRS_ERKRS DIRECTED    KOKRS   ERKRS   KOKRS_4500  ERKRS_IDEA      1       #808080 1   FALSE

I have successfully created nodes dynamically using apoc.create.node with my nodes file. The node labels = SOURCE_TYPE or TARGET_TYPE. The node KEY attribute = SOURCE_KEY or TARGET_KEY. The relationship is the LABEL column.

Now am challenged with creating relationships as the MATCH clause does not accept a label from my file - this is my script:

USING PERIODIC COMMIT 500 LOAD CSV WITH HEADERS  FROM 'file:///IDES__Edges1.csv' AS line
MATCH (x:line.SOURCE_TYPE {key:line.SOURCE_KEY}), (y:line.TARGET_TYPE {key:line.TARGET_KEY})
CALL apoc.create.relationship(x, line.LABEL, y) YIELD rel RETURN count(*)

I get this error...

    Neo.ClientError.Statement.SyntaxError: Invalid input '.': expected an identifier character, whitespace, NodeLabel, a property map, ')' or a relationship pattern (line 2, column 15 (offset: 103))
"   MATCH (x:line.SOURCE_TYPE {key:line.SOURCE_KEY}), (y:line.TARGET_TYPE {key:line.TARGET_KEY})"

Does anyone have any ideas on how to approach this? I am SO CLOSE to solving my problem! Any help appreciated. John

like image 817
johnaco Avatar asked Nov 02 '25 17:11

johnaco


1 Answers

This illustrates why it's recommended to process individual CSV files per node type, so you'll always be able to know what label to hard code into your query.

This is a requirement for Cypher because when labels are hardcoded, the planner to leverage metadata in the db to aid in how to efficiently plan query execution (evaluation of dynamic labels would have to happen during execution...that's useless to the planner that must plan the query before execution).

For this kind of case, it might be best to add a second, more general label to all of the nodes of each of the types added, then create an index using the key property and that general label, and use that general label for lookup when creating the relationships.

So after the general label (let's just call it :Node for now) is applied, and an index created on :Node(key), it's as simple as:

USING PERIODIC COMMIT 500 LOAD CSV WITH HEADERS  FROM 'file:///IDES__Edges1.csv' AS line
MATCH (x:Node {key:line.SOURCE_KEY}), (y:Node {key:line.TARGET_KEY})
CALL apoc.create.relationship(x, line.LABEL, y) YIELD rel 
RETURN count(*)

This assumes of course that keys are unique among all the nodes with all of the given labels. If that's not the case, then a different approach will be needed.

like image 53
InverseFalcon Avatar answered Nov 04 '25 12:11

InverseFalcon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!