7

I'm having trouble converting the following Cypher query to the Neo4jClient syntax.

MATCH n WHERE NOT (HAS (n.User)) OR n.User = "username" RETURN n

This is what I currently have with the addition of some relationship logic and the omission of the HAS logic

var results = Client.Cypher
               .OptionalMatch("(result)-[connection:Connection]-(result2)")
               .Where((Result result) => result.User == username)
               .Return((result, connection, result2) => new Neo4jResultSingle()
               {
                   SearchedNode = result.As<Node<Result>>(),
                   RelationshipConnection = connection.As<RelationshipInstance<Connection>>(),
                   Relationship = connection.As<RelationshipInstance<ConnectionRelationship>>(),
                   RelationshipedNode = result2.As<Node<Result>>()
               }).Results.ToList();
Jeff H
  • 125
  • 1
  • 1
  • 5

3 Answers3

10

HAS was superseded by EXISTS()

From the latest docs: Property existence checking

MATCH (n) WHERE EXISTS(n.User) RETURN n

for opposite match add NOT before

MATCH (n) WHERE NOT EXISTS(n.User) RETURN n
vladkras
  • 16,483
  • 4
  • 45
  • 55
  • 2
    The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. – Oliver Meyer Jan 15 '23 at 10:06
8

In Neo4j 4.3,

The exists() function has been deprecated for property existence checking and has been superseded by IS NOT NULL.

So please use

MATCH (n) 
WHERE n.User IS NOT NULL 
RETURN n

OR

MATCH (n) 
WHERE n.User IS NULL 
RETURN n

In your code specifically,

var results = Client.Cypher
       .Match("(result)-[connection:Connection]-(result2)")
       .Where("WHERE n.User IS NULL OR n.User = {username}")
       .WithParams(new { username = username })
       .Return((result, connection, result2) => new Neo4jResultSingle()
       {
           SearchedNode = result.As<Node<Result>>(),
           RelationshipConnection = connection.As<RelationshipInstance<Connection>>(),
           Relationship = connection.As<RelationshipInstance<ConnectionRelationship>>(),
           RelationshipedNode = result2.As<Node<Result>>()
       })
       .Results
       .ToList();
Thennan
  • 788
  • 5
  • 13
2

Looking at a combination of your original query and your C# maybe the following might help?

var results = Client.Cypher
           .Match("(result)-[connection:Connection]-(result2)")
           .Where("WHERE NOT HAS(n.User) OR n.User = {username}")
           .WithParams(new { username = username })
           .Return((result, connection, result2) => new Neo4jResultSingle()
           {
               SearchedNode = result.As<Node<Result>>(),
               RelationshipConnection = connection.As<RelationshipInstance<Connection>>(),
               Relationship = connection.As<RelationshipInstance<ConnectionRelationship>>(),
               RelationshipedNode = result2.As<Node<Result>>()
           })
           .Results
           .ToList();

This rewrites your WHERE clause to include both the HAS and username logic, whilst parameterising it to cache the query plan and protect against injection.

ceej
  • 1,863
  • 1
  • 15
  • 24