Chris Staikos
Chris Staikos

Reputation: 1160

Is it possible to merge using data-driven node or relationship labels?

I'm working with prepared statements via the Neo4J JDBC driver, and have a need to create node and relationship labels whose names are driven by the data we will be receiving.

For example, I'd like to create a prepared statement along these lines:

MERGE (test:{1} {id: {2}) ON CREATE SET test.id = {2}

OR

MERGE (test:Test)-[:{1}]->(test2:Test)

These don't currently work, as it seems Neo4J doesn't interpret the placeholder {1} as a placeholder, instead seeing it as an invalid label name.

Another possibility I'm exploring is that we may be able to extend Cypher via a stored procedure, though I suspect we may run into the same limitation.

Hoping someone can provide some insight as to whether there is any way to accomplish this with Cypher.

Thanks!

UPDATE:

An answer below suggests using APOC's apoc.create.node procedure, but what I need is to merge on a dynamic label. Updated the title to reflect this.

Upvotes: 3

Views: 519

Answers (3)

arganzheng
arganzheng

Reputation: 1334

After trying almost half a day, I finally find out this method:

UNWIND {batch} as row MERGE (n { id: row.id }) SET n += row.properties WITH n CALL apoc.create.addLabels(id(n), [n.label]) YIELD node RETURN node and the performance is almost the same as purely MERGE.

Many thanks for this refer: SET label : pass label name as parameter

Upvotes: 0

Chris Staikos
Chris Staikos

Reputation: 1160

I ended up using a different procedure from APOC - apoc.cypher.doIt, as it turns out APOC doesn't have a way to merge with dynamic labels as of yet. See feature request: https://github.com/neo4j-contrib/neo4j-apoc-procedures/issues/271

Below is what I ended up doing. Note that the requirement was to iterate (in this case using UNWIND) over a collection and merge nodes with dynamic labels pulled from this collection, and then merge a relationship between a pre-existing node and this new node:

WITH myNode, myList
UNWIND categories AS catArray
WITH myNode, 'MERGE (cat:' + catArray[0] + ' {value: "' + catArray[1] + '" }) ON CREATE SET cat.value = \"' + catArray[1] + '\" RETURN cat' AS cypher
CALL apoc.cypher.doIt(cypher, {}) YIELD value
WITH myNode, value.cat as cat
MERGE (myNode)-[:IN_CATEGORY]->(cat)

Upvotes: 2

Dave Bennett
Dave Bennett

Reputation: 11216

You can use APOC to create dynamic relationships. Similar APOC procedures exist for creating nodes with dynamic labels or adding dynamic labels to nodes.

MERGE (test:Test {name: 'Test'})
WITH test
MERGE (test2:Test {name: 'Test 2'})
WITH test, test2
CALL apoc.create.relationship(test, {new_rel_type}, {}, test2) YIELD rel
RETURN test, test2, rel

Upvotes: 1

Related Questions