# Check if node exists and use the result as a condition

**URL:** <https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069>\
**Category:** Cypher\
**Created:** [January 14, 2021, 6:14pm UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069 "2021-01-14T18:14:13Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![janezic](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/janezic/32/6712_2.png) [@janezic](https://community.neo4j.com/u/janezic)\
**Post date:** [January 14, 2021, 6:14pm UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/1 "2021-01-14T18:14:13Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![clem](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/clem/32/4364_2.png) [@clem](https://community.neo4j.com/u/clem)\
**Post date:** [January 14, 2021, 7:32pm UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/2 "2021-01-14T19:32:10Z")

</div>

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:

```auto
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!

---

<div class="post-metadata">

**Author:** ![janezic](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/janezic/32/6712_2.png) [@janezic](https://community.neo4j.com/u/janezic)\
**Post date:** [January 14, 2021, 8:56pm UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/3 "2021-01-14T20:56:32Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![clem](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/clem/32/4364_2.png) [@clem](https://community.neo4j.com/u/clem)\
**Post date:** [January 14, 2021, 9:09pm UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/4 "2021-01-14T21:09:59Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![dominicvivek06](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/dominicvivek06/32/5034_2.png) [@dominicvivek06](https://community.neo4j.com/u/dominicvivek06)\
**Post date:** [January 15, 2021, 12:32am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/5 "2021-01-15T00:32:56Z")

</div>

Hi @janezic ,

hope this works ... try this CASE expression

> **[Expressions - Cypher Manual](https://neo4j.com/docs/cypher-manual/current/syntax/expressions/)**
>
> This section contains an overview of expressions in Cypher with examples.

```auto
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 │
└─────────┴────────────────────┘

```

---

<div class="post-metadata">

**Author:** ![clem](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/clem/32/4364_2.png) [@clem](https://community.neo4j.com/u/clem)\
**Post date:** [January 15, 2021, 1:03am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/6 "2021-01-15T01:03:18Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![dominicvivek06](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/dominicvivek06/32/5034_2.png) [@dominicvivek06](https://community.neo4j.com/u/dominicvivek06)\
**Post date:** [January 15, 2021, 1:11am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/7 "2021-01-15T01:11:05Z")

</div>

@clem , please, visit the CASE statement documentation -\> [Expressions - Cypher Manual](https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#syntax-simple-case). It can be simply changed to condition. CASE statements exists from RDBMS too.

@janezic

```auto

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 │
└─────────┴────────────────────┘

```

---

<div class="post-metadata">

**Author:** ![janezic](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/janezic/32/6712_2.png) [@janezic](https://community.neo4j.com/u/janezic)\
**Post date:** [January 15, 2021, 7:34am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/8 "2021-01-15T07:34:46Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![tard\_gabriel](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/tard_gabriel/32/28033_2.png) [@tard\_gabriel](https://community.neo4j.com/u/tard_gabriel)\
**Post date:** [January 15, 2021, 7:48am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/9 "2021-01-15T07:48:59Z")

</div>

> [@janezic](#):
>
> I just want to get back TRUE or FALSE if a node with a certain label and 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.

---

<div class="post-metadata">

**Author:** ![tard\_gabriel](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/tard_gabriel/32/28033_2.png) [@tard\_gabriel](https://community.neo4j.com/u/tard_gabriel)\
**Post date:** [January 15, 2021, 8:03am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/10 "2021-01-15T08:03:28Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![clem](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/clem/32/4364_2.png) [@clem](https://community.neo4j.com/u/clem)\
**Post date:** [January 15, 2021, 8:09am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/11 "2021-01-15T08:09:37Z")

</div>

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`

```auto
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`

---

<div class="post-metadata">

**Author:** ![janezic](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/janezic/32/6712_2.png) [@janezic](https://community.neo4j.com/u/janezic)\
**Post date:** [January 15, 2021, 8:14am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/12 "2021-01-15T08:14:37Z")

</div>

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

THANK YOU!!!

---

<div class="post-metadata">

**Author:** ![tard\_gabriel](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/tard_gabriel/32/28033_2.png) [@tard\_gabriel](https://community.neo4j.com/u/tard_gabriel)\
**Post date:** [January 15, 2021, 8:19am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/13 "2021-01-15T08:19:20Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![clem](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/clem/32/4364_2.png) [@clem](https://community.neo4j.com/u/clem)\
**Post date:** [January 15, 2021, 8:23am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/14 "2021-01-15T08:23:51Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![astrosam](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/astrosam/32/26153_2.png) [@astrosam](https://community.neo4j.com/u/astrosam)\
**Post date:** [July 14, 2023, 2:48am UTC](https://community.neo4j.com/t/check-if-node-exists-and-use-the-result-as-a-condition/32069/15 "2023-07-14T02:48:24Z")

</div>

I just found this thread.

I have some comments about the proposed solution:

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

```

The above solution is not appropriate if the OPTIONAL MATCH can find multiple (N) matches. That is because in that case it would: (1) do the work to find all N matches and not stop after finding just the first one, and (2) it would return N Predicate values (all true).

Here is one simple way to fix both issues:

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

```

There are other solutions as well, including using the EXISTS() function properly.

The EXISTS function must be passed a pattern _that has a relationship_. Here is a tricky way to use a 0-length variable relationship pattern with EXISTS to match a node (that does not need to have a relationship). It is, unfortunately, hard to read; but it does work.

```auto
RETURN EXISTS((:User{user_id:1})-[*0]-()) AS Predicate

```

Also, neo4j 5.3 added the [EXISTS subquery](https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries), which is a little easier to read:

```auto
RETURN EXISTS { (:User{user_id:1}) } AS Predicate

```
