0

I am creating a word tree but when I execute this cypher query:

word = "MATCH {} MERGE {}-[:contains]->(w:WORD {{name:'{}'}}) RETURN w"
    .format(parent_node, parent_node, locality[i])

where parent_node has a type Node

It throws this error:

py2neo.cypher.error.statement.InvalidSyntax: Can't create `n8823` with properties or labels here. It already exists in this context

formatted query looks like this:

'MATCH (n8823:HEAD {name:"sanjay"}) MERGE (n8823:HEAD {name:"sanjay"})-[:contains]->(w:WORD {name:\'colony\'}) RETURN w'
blackmamba
  • 1,952
  • 11
  • 34
  • 59

2 Answers2

1

The formatted query is broken and won't work, but I also don't see how that could be what the formatted query actually looks like. When you do your string format you pass the same parameter (parent_node) twice so the final string should repeat whatever that parameter looks like. It doesn't, and instead has two different patterns for the match and merge clauses.

Your query should look something like

MATCH (n8823:Head {name: "sanjay"})
MERGE (n8823)-[:CONTAINS]->(w:Word {name: "colony"})
RETURN w

It's probably a bad idea to do string formatting on a Node object. Better to either use property values from your node object in a Cypher query to match the right node (and only the variable that you bind the matched node to in the merge clause) or use the methods of the node object to do the merge.

jjaderberg
  • 9,844
  • 34
  • 34
0

Although the MERGE clause is able to bind identifiers (like n8823), Cypher unfortunately does not allow MERGE to re-bind an identifier that had already been bound -- even if it would not actually change the binding. (On the other hand, the MATCH clause does allow "rebinding" to the same binding.) Simply re-using a bound identifier is OK, though.

So, the workaround is to change your Cypher query to re-use the bound identifier. Also, the recommended way to dynamically specify query data without changing the overall structure of a query is to use "query parameters". For py2neo, code along these lines should work for you (note that the parent_name variable would contain a name string, like "sanjay"):

from py2neo import Graph
graph = Graph()
cypher = graph.cypher
results = cypher.execute(
  "MATCH (foo:{name:{a}}) MERGE (foo)-[:contains]->(w:WORD {{name:'{b}'}}) RETURN w",
  a=parent_name, b=locality[i])
cybersam
  • 63,203
  • 6
  • 53
  • 76
  • Actually, I can't do this. I have added this statement in a loop, hence takes the value as the loop iterates. So foo's label keeps on changing. – blackmamba Dec 14 '15 at 06:09
  • I tried this: MATCH {} CREATE UNIQUE {}-[:contains]-(w:WORD {{name:'{}'}}) RETURN w, I am facing the same issue. – blackmamba Dec 14 '15 at 06:11