Test if relationship exists in neo4j / spring data
Asked Answered
S

3

6

I'm trying to solve the simple question, if in a graph with the "knows" relationship, some person A knows some person B. Ideally I would answer this question with either true or false but I'm failing to solve this.

I found the following in another StackOverflow question which is almost what I want, except that apart from just answering my question, it also changes the graph:

MATCH  (p:Person {userId: {0}}), (b:Person {userId: {1}}) 
MERGE (p)-[r:KNOWS]->(b) 
ON CREATE SET r.alreadyExisted=false 
ON MATCH SET r.alreadyExisted=true 
RETURN r.alreadyExisted;

In the end I would like to put this in a Spring Neo4J repository like this

public interface PersonRepository extends GraphRepository<Person> {
    boolean knows(final Long me, final Long other);
}

That means if there is a way to do it without cypher - using Springs Query and Finder methods, that would be fine too.

Subconscious answered 3/2, 2017 at 10:35 Comment(0)
V
20

The Cypher query for this is a simple one, the key here is the EXISTS() function, which will return a boolean value if the pattern given to the function exists in the graph.

Here's the Cypher query.

MATCH  (p:Person {userId: {0}}), (b:Person {userId: {1}}) 
RETURN EXISTS( (p)-[:KNOWS]-(b) )

You can even make it more concise:

RETURN EXISTS( (:Person {userId: {0}})-[:KNOWS]-(:Person {userId: {1}}) )
Vining answered 3/2, 2017 at 10:54 Comment(2)
Thanks so much - I was trying the EXISTS() function but couldn't figure out how to state that a relation ship has to exist! One small change was necessary though, my "KNOWS" relationship is directional, so A can know B without B knowing A. I changed it to (p)-[:KNOWS]->(b) and it worked!Subconscious
Thanks a lot! This was very helpful. Thought it's worth noting that the two expressions work slightly differently. For the first query, for all p and b pairs, the truth state of the existence of the relationship is returned. For the second, only the existence of such a relationship is indicated.Hultin
K
5

As a complementary note to what @InverseFalcon said

// first
MATCH  (p:Person {userId: {0}}), (b:Person {userId: {1}}) 
RETURN exists( (p)-[:KNOWS]-(b) )
// second
RETURN exists( (:Person {userId: {0}})-[:KNOWS]-(:Person {userId: {1}}) )

There is a difference between the two examples that were provided:

the first one builds a Cartesian product between disconnected patterns.

If a part of a query contains multiple disconnected patterns, this will build a Cartesian product between all those parts. This may produce a large amount of data and slow down query processing. While occasionally intended, it may often be possible to reformulate the query that avoids the use of this cross product, perhaps by adding a relationship between the different parts or by using OPTIONAL MATCH

It merely means if you have 5 persons in your database P={0,1,2,3,4};

  • the first query nearly checks existence |A|x|A| = 5x5 = 25 possible path between every two-person where the first Person node has id equals to` 0 and the second Person node has id equals to 1.
  • the second query checks existence of the path from a Person node with id 0 and the Person node with id 1.

also cause exists can be a function and keyword, convention suggests to write functions as lowercase and others as uppercase.

// Use an existential sub-query to filter.
WHERE EXISTS {
  MATCH (n)-->(m) WHERE n.userId = m.userId
} 

also, you can rename the return value to some new variable for example:

RETURN exists( (:Person {userId: {0}})-[:KNOWS]-(:Person {userId: {1}}) ) as knows
Karie answered 6/1, 2021 at 21:14 Comment(0)
I
0

As below, cypher query worked for me.

MATCH  (sNode{GUID:'ID3456'}), (aNode{ID:AD4567}) RETURN exists( (sNode)-[:my_Relation]-(aNode) )

This gave a result like below

[{'exists( (sNode)-[:my_Relation]-(aNode) )': False}]
Inequality answered 15/3, 2023 at 11:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.