Search code examples
c#neo4jneo4jclient

neo4j query construction SyntaxException


I am writing a .NET airport application using neo4j for the first time. I have an API and can get my objects (Airports in this case) that are in the database. I can also create new Airports with

public void Post([FromUri]string name, [FromUri]string code, [FromUri]string city, [FromUri]string state)
{
    string query = "(:Airport{name:'" + name + "',code:'" + code.ToUpper() + "',city:'" + city + "',state:'" + state.ToUpper() + "'})";
    var q = WebApiConfig.GraphClient.Cypher.Create(query);
    q.ExecuteWithoutResults();
}

That works fine. But I also want to make sure that the Airport does not already exist in the database. So I have tried to add in the code:

var existing = WebApiConfig.GraphClient.Cypher.Match("(a:Airport)")
            .Where((Airport a) => a.Code.Equals(code.ToUpper()))
            .Return(a => a.As<Airport>());

But when I run this code section it always throws a SyntaxException. I think that it is in the construction of the where clause.

My Airport class is

public class Airport
{
    public string City { get; set; }
    public string State { get; set; }
    public string Code { get; set; }
}

The current resource I am using is https://github.com/Readify/Neo4jClient/wiki/cypher.

Two questions:

  1. What am I missing here?
  2. Are there other resources out there that would help me out?

Thank you


Solution

  • The SyntaxException is being thrown because Neo4jClient doesn't know how to deal with .Equals - if you take your query and look at the existing.Query.DebugQueryText you'll see it output (I'm passing in 'lax' as code):

    MATCH (a:Airport)
    WHERE a.Code"lax"
    RETURN a
    

    The SyntaxException comes from the WHERE a.Code"lax" - so you need to firstly change to using the == operator instead:

    var existing = gc.Cypher.Match("(a:Airport)")
            .Where((Airport a) => a.Code == code.ToUpper())
            .Return(a => a.As<Airport>());
    

    Now if we look at the QueryDebugText we get:

    MATCH (a:Airport)
    WHERE (a.Code = "lax")
    RETURN a
    

    But "lax" is lower case - we put ToUpper() there, so it should be "LAX" right??

    A subtle nuance of Neo4jClient is that it needs to have the details as they need to be for the query, so doing:

    code = code.ToUpper();
    var existing = gc.Cypher.Match("(a:Airport)")
            .Where((Airport a) => a.Code == code)
            .Return(a => a.As<Airport>());
    

    will generate:

    MATCH (a:Airport)
    WHERE (a.Code = "LAX")
    RETURN a
    

    You can use methods like ToUpper but you end up having to put them in a string.Format or interpolation:

    var existing = gc.Cypher.Match("(a:Airport)")
            .Where($"(a.Code = \"{code.ToUpper()}\")")
            .Return(a => a.As<Airport>());
    

    Which is a pain, as you need to remember the \" and open/close parentheses.

    General tip is to always look at the DebugQueryText to see what is being generated.

    Your second question as to more resources - I'm afraid there isn't :(