Test if relationship exists in neo4j / spring data

12,471

Solution 1

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}}) )

Solution 2

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
Share:
12,471
schneida
Author by

schneida

Updated on June 13, 2022

Comments

  • schneida
    schneida almost 2 years

    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.

  • schneida
    schneida about 7 years
    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!