neo4j / neo4j

Graphs for Everyone
http://neo4j.com
GNU General Public License v3.0
13.31k stars 2.38k forks source link

Parameterized labels in CREATE statements #1809

Open Marsaly opened 10 years ago

Marsaly commented 10 years ago

Is it possible to clone arbitrary nodes and relationships in a single Cypher neo4j 2.0 query? 'Arbitrary' reads 'without specifying their labels and relationship types'. Something like:

MATCH (node1:NodeType)-[e]->(n)
CREATE (clone: labels(n)) set clone=n set clone.prop=1 
CREATE (node1)-[e1:type(e)]->(clone) set e1=e set e1.prop=2

is not valid in Cypher, so one cannot simply get labels from one node or relationship and assign them to another, because labels are compiled into the query literally.

Sure, labels and relation types are important for MATCH and WHERE for producing effective query plan, but isn't CREATE making another case?

systay commented 10 years ago

What you are describing makes good sense. Still a number of open questions though - we can't simply allow expressions in place of the label name. That would make the language ambiguous, which we don't want. I'll give you an example:

WITH "OtherLabel" as Label
CREATE (node:Label)

This is a contrived example, but I hope you understand what I'm after - we need syntax changes to make this possible. Any ideas?

Marsaly commented 10 years ago

This could be something like classic EVAL, but for labels only. EVAL takes a string or a list of strings and may be used in places where labels are specified in create/update clauses. So your example turns into:

WITH "OtherLabel" as Label
CREATE (node:EVAL(Label))

which evaluates to

CREATE (node:OtherLabel)

and my example from the first post turns into

MATCH (node1:NodeType)-[e]->(n)
CREATE (clone: EVAL(labels(n))) set clone=n set clone.prop=1 
CREATE (node1)-[e1:EVAL(type(e))]->(clone) set e1=e set e1.prop=2

If EVAL name seems too common, something more specialized may be used, say DYNAMIC_LABEL().

This mechanism can also be described as a macro, acting upon one create/update clause of a Cypher query and having access to bindings in that clause's context.