Search code examples
neo4jcypherneo4jclient

Neo4jClient error - SyntaxException: Parenthesis are required to identify nodes in patterns using .CreateUnique


I am fairly new to Neo4j and Neo4jClient and I am just starting to write some fluent Cypher to create a relationship, if it does not already exist. I am running Neo4j 2.0 beta, as the examples in the Neo4jClient wiki appear to be for 2.0.

When I run it I get the following error:

SyntaxException: Parenthesis are required to identify nodes in patterns
"CREATE UNIQUE app-[:APP_OF]->{root}"
                  ^

The ^ points at the hyphen after app.

I would greatly appreciate it if anyone could tell me what I have done wrong.

This is the two cypher queries that create an App, if it does not already exist, and then create the relationship, if it does not exist.

// Create App
client.Cypher
.Merge("(app:App {Id: {id}})")
.OnCreate("app")
.Set("app = {newApp}")
.WithParams(new { id = a.Id, newApp = a })
.ExecuteWithoutResults();

// Create Relationship
client.Cypher
.Match("(app:App)")
.Where((App app) => app.Id == a.Id)
.CreateUnique("app-[:APP_OF]->{root}") // this is the error line
.WithParam("root", client.RootNode)
.ExecuteWithoutResults();

I wonder if there is a way to combine these into one query also?

And should I bother connecting to the root node, or is it ok for the App nodes to float. I understand that a start node is no longer required, so is a connection to the root not required? I would still need this code for other relationships though.

Many thanks for your help :)

Edit: This is the example I have followed from https://github.com/Readify/Neo4jClient/wiki/cypher-examples

graphClient.Cypher
  .Match("(user1:User)", "(user2:User)")
  .Where((User user1) => user1.Id == 123)
  .AndWhere((User user2) => user2.Id == 456)
  .CreateUnique("user1-[:FRIENDS_WITH]->user2")
  .ExecuteWithoutResults();

Solution

  • This problem is how you're supplying the parameters:

    .CreateUnique("app-[:APP_OF]->{root}")
    .WithParam("root", client.RootNode)
    

    You can't pass in a node reference like that.

    You'd need to use the START clause to bring the node into the query:

    client.Cypher
        .Start(new { root = client.RootNode })
        .Match("(app:App)")
        .Where((App app) => app.Id == a.Id)
        .CreateUnique("app-[:APP_OF]->root")
        .ExecuteWithoutResults();
    

    Now, answering your next question about combining them, this should work:

    client.Cypher
        .Start(new { root = client.RootNode })
        .Merge("(app:App {Id: {id}})")
        .OnCreate("app")
        .Set("app = {newApp}")
        .CreateUnique("app-[:APP_OF]->root") // this is the error line
        .WithParams(new { id = a.Id, newApp = a })
        .ExecuteWithoutResults();
    

    (Note: I haven't tried running that though: I just typed it in here.)

    HOWEVER you don't want to use client.RootNode. That's an API for the reference node, which is deprecated in 2.0: http://docs.neo4j.org/chunked/milestone/deprecations.html. We only needed the root node before we had labels. In this scenario, you seem to be using it so that you can find all the app nodes again in the future, however you don't need to do that, because you can find them based on their label now.