cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Check if node exists and use the result as a condition

janezic
Graph Voyager

Sorry, to ask this question for the 100th time, but none of the previous posts was similar to my problem: I just want to get back TRUE or FALSE if a node with a certain label and a certain value of a property exists.

(u:User {user_id: 1} => TRUE / FALSE

All other posts where about MERGE and so on, but I don't want to create anything, I want to use it as a condition in an apoc.do.when-function.

1 ACCEPTED SOLUTION

If you add IS NOT null then you will get a true when property has the value /false when the property doesn't have the value.

I hadn't thought of using OPTIONAL. Clever! Also you don't need exists(); you can just test n for null

OPTIONAL MATCH (n:User{user_id:1})
RETURN n IS NOT NULL AS Predicate

(note exists(n) doesn't work.)

This is a good example of using OPTIONAL.

[added] Without OPTIONAL and if User with user_id = 1 doesn't exist, then the MATCH returns no records which is different than returning null. Subtle!

Also reminder for Cypher beginners: the test n <> null is incorrect for testing null/non-null. This is correct: n IS NOT null

View solution in original post

13 REPLIES 13

clem
Graph Steward

This is tricky! the exists() function doesn't work the way I had hoped... and you can't compare the MATCH results with null.

but this works:

MATCH (u:User {user_id: 1})
WITH count(*) as count
CALL apoc.when (count > 0, // won't work so well if user_id isn't unique...
"RETURN true AS bool",     // one or more users with user_id = 1
"RETURN false AS bool",    // no users with user_id = 1
{count:count}
) YIELD value
return value.bool

There may be a better way to do this, but I don't know..

Remember apoc.do.when is for when you want to change the DB, apoc.when is if you are just reading.

[added] a better solution is further towards the end of this thread!

janezic
Graph Voyager

Thanks a lot, I have tried it with exists() and comparing with NULL - and as you said without any success. I did not come to the conclusion to try it with count().

I basically don't understand why Cypher (or at least APOC) does not provide a function for that.

I don't know either... The Cypher language could evolve to do this, but it's still a relatively young language, so maybe it will get extended.

Hi @janezic ,

hope this works ... try this CASE expression

merge (p:Person{name:"Dominic",db:"Neo4j"});
Added 1 label, created 1 node, set 2 properties, completed after 6 ms.

merge (p:Person{name:"Kumar"});
Added 1 label, created 1 node, set 1 property, completed after 6 ms.


match (n) return (n)
╒═══════════════════════════════╕
│"n"                            │
╞═══════════════════════════════╡
│{"name":"Dominic","db":"Neo4j"}│
├───────────────────────────────┤
│{"name":"Kumar"}               │
└───────────────────────────────┘

MATCH (p:Person)
RETURN p.name,
CASE
WHEN exists(p.db)  THEN true
ELSE false END AS db_property_status;

╒═════════╤════════════════════╕
│"p.name" │"db_property_status"│
╞═════════╪════════════════════╡
│"Dominic"│true                │
├─────────┼────────────────────┤
│"Kumar"  │false               │
└─────────┴────────────────────┘

Sorry, this solves different question: whether a property exists, not whether a node with a specific value exists.

@clem , please, visit the CASE statement documentation -> Expressions - Neo4j Cypher Manual. It can be simply changed to condition. CASE statements exists from RDBMS too.

@janezic



match (n) return (n)
╒═══════════════════════════════╕
│"n"                            │
╞═══════════════════════════════╡
│{"name":"Dominic","db":"Neo4j"}│
├───────────────────────────────┤
│{"name":"Kumar"}               │
└───────────────────────────────┘

MATCH (p:Person)
RETURN p.name,
CASE
WHEN p.db="Neo4j"  THEN true
ELSE false END AS db_property_status;

╒═════════╤════════════════════╕
│"p.name" │"db_property_status"│
╞═════════╪════════════════════╡
│"Dominic"│true                │
├─────────┼────────────────────┤
│"Kumar"  │false               │
└─────────┴────────────────────┘

Good Morning,
thank you, but no, this is basically not exactly what I was looking for, because it gives me all users with all their email-addresses with a additional column true/false.

Of course you could filter it again, but this is a very expensive query.

I just want to know, if a node with a certain value of a property exists.

Wow, at the beginning I was pfff that's super easy...hoo no that's not indeed.
Funny, I like challenge, I didn't solve it yet but I see a OPTIONAL MATCH clause as an work around solution.

And by the way, null laws of neo4j implies that null is not equal to null since null is nothing not a value and then since we don't know what it is you can't compare something you don't know with something you don't know.

OPTIONAL MATCH (n:Label {property:value})
RETURN exists(n.property) AS Predicate

It will give you one row with true or null as output, it's not exactly the end result wanted but it's the closer one I got for now.

If you add IS NOT null then you will get a true when property has the value /false when the property doesn't have the value.

I hadn't thought of using OPTIONAL. Clever! Also you don't need exists(); you can just test n for null

OPTIONAL MATCH (n:User{user_id:1})
RETURN n IS NOT NULL AS Predicate

(note exists(n) doesn't work.)

This is a good example of using OPTIONAL.

[added] Without OPTIONAL and if User with user_id = 1 doesn't exist, then the MATCH returns no records which is different than returning null. Subtle!

Also reminder for Cypher beginners: the test n <> null is incorrect for testing null/non-null. This is correct: n IS NOT null

Wow, the solution is so simple and so hard to find on the other hand.

THANK YOU!!!

I added a suggestion to the documentation for OPTIONAL MATCH.

This is a great example!

I've learned a lot! Thanks for showing us OPTIONAL MATCH. I hadn't quite appreciated what it could do.

The key here is this fact:

MATCH return nothing if he finds nothing
OPTIONAL MATCH always return at least null

Thanks clem I was looking for an operator for the null or something like that.

I didn't know you could use a lonely optional match

We did it, next challenge.