添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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.

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!

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.

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,
WHEN exists(p.db)  THEN true
ELSE false END AS db_property_status;
╒═════════╤════════════════════╕
│"p.name" │"db_property_status"│
╞═════════╪════════════════════╡
│"Dominic"│true                │
├─────────┼────────────────────┤
│"Kumar"  │false               │
└─────────┴────────────────────┘
              

@clem , please, visit the CASE statement documentation -> Expressions - 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, 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.

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.

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

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 :thinking:

We did it, next challenge.

I just found this thread.

I have some comments about the proposed solution:

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:

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.

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

Also, neo4j 5.3 added the EXISTS subquery, which is a little easier to read:

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