cancel
Showing results forΒ
Did you mean:Β

## Understanding the all() Predicate Function

Node Clone

I'm trying to use the `all()` Predicate Function in my query, but it's not working as expected, so I decided to experiment a little with the Movies graph.

Given that I want to find all paths where actors acted in movies that were released after 2000, I tried using the `all()` function, like so -

``````MATCH path=(p:Person)-[:ACTED_IN]->(movie:Movie)
WHERE all(n in nodes(path) WHERE (n:Movie) AND n.released > 2000)
RETURN path
LIMIT 20
``````

This is similar to the example given in the documentation, that says -

``````MATCH p =(a)-[*1..3]->(b)
WHERE a.name = 'Alice' AND b.name = 'Daniel' AND ALL (x IN nodes(p) WHERE x.age > 30)
RETURN p
``````

All nodes in the returned paths will have an `age` property of at least '30' .

However, my query doesn't return anything.

If I change the query to see all `nodes` in the path -

``````MATCH path=(p:Person)-[:ACTED_IN]->(movie:Movie)
RETURN nodes(path)
LIMIT 20
``````

Then there are several nodes in the path where the movie was released after 2000 -

Is there something I'm missing about how `all()` works?

8 REPLIES 8
Graph Buddy

HI manish ,
MATCH path=(p:Person)-[:ACTED_IN]->(movie:Movie)
WHERE all(n in nodes(path) WHERE (n:Movie) AND n.released > 2000)
RETURN path
LIMIT 20

in this query , when you do ALL() , it means all the nodes in that path must qualify the filter you put inside that i.e n: Movie AND n.released > 2000
But , here, when you do nodes(path) , it includes the p:Person node too , so the person node cannot qualify the n:Movie filter .. since one node failed the condintion, ALL () will also fail .. thats why it wont return any output in anycase.

Instead, you can do the following ,
MATCH path=(p:Person)-[:ACTED_IN]->(movie:Movie)
WHERE movie.released > 2000
WITH p , movie LIMIT 20
RETURN p , COLLECT(movie) as movies

Hello, Thank You for responding!

I was under the impression that my query would only consider nodes of type `Movie` in `nodes(path)`, because I specifically added in this clause - `WHERE (n:Movie)`,
before adding `AND n.released 2000`.

I thought this would select only the `Movie` nodes from the path, and apply the `released > 2000` filter on those `Movie` nodes, because obviously the `released` property exists only on `Movie` nodes.

Graph Buddy

nodes(path) -> this function will return all nodes the in the path ,
ex : nodes(path) = [ personNode , movieNode]
ALL (x IN nodes(path) WHERE (condition))
so , you are iterating through [ personNode , movienode,movie node] and applying filter ,
the filter fails with person node and so the ALL function .

When you do n:Movie ,you are asking to filter nodes(note that you are not selecting) which have label Movie, this means your filter returns true for all movie nodes but false for person node.
but ALL() wants all the rows passed to satisfy the where condition (ie.return true)

WHERE is for filtering the selected rows ..MATCH does the actual select part

Neo4j

Consider the results in the image you posted. Each row here contains a list of the nodes in the path (or at least it displays their properties). Because of your pattern `(p:Person)-[:ACTED_IN]->(movie:Movie)`, each path will consist of two nodes: a :Person node and a :Movie node that the person acted in.

Since you're using `all(n in nodes(path) ...`, that means, per path, every one of those nodes needs to adhere to your WHERE clause: every node needs to be a :Movie node (which is impossible because of your pattern), and each node needs a `released` property > 2000.

If you had used `any()` instead of `all()`, then the predicate would be satisfied by finding, in the path, at least one node satisfying the conditions, and you would have gotten results back.

Thank You! I guess the comparison between `all()` and `any()` makes it clear. For some reason, I thought using `WHERE`, like (`WHERE (n:Movie)`), inside `all()` would first filter out all `Movie` nodes, and then apply the `all()` predicate for all such nodes.

I can see how that could seem confusing. You would need to filter the list used separately.

For example, if we wanted to filter the nodes in the path to only be :Movie nodes and then filter by the released property you could do this:

``````MATCH path=(p:Person)-[:ACTED_IN]->(movie:Movie)
WHERE all(n in [node in nodes(path) WHERE node:Movie] WHERE (n:Movie) AND n.released > 2000)
RETURN path
LIMIT 20
``````

So rather than just use `nodes(path)`, we need to filter this first, in this case using a list comprehension to filter the list such that every node in nodes(path) meets the criteria of being a :Movie node. Now that the list is filtered to only be :Movie nodes (these should be single-element lists now), the `all()` list predicate may evaluate to true for some of the paths matched.

Thank You so much! Your explanation makes it a lot more clearer.

Just so I know I'm getting it right -

this is done using this list comprehension - `[node in nodes(path) WHERE node:Movie]`

If this works, then, from what I think, the resulting list should contain only `Movie` nodes? If that is the case, then would it be correct to remove the redundant `WHERE (n:Movie)` in the `any()` function, so that it becomes -

``````WHERE all(n in [node in nodes(path) WHERE node:Movie] WHERE n.released > 2000)
``````

I did run this query, and it seems to return something, so I'm guessing this must be correct -

Yes, just like that!

Of course the usage of `all()` makes more sense in a longer pattern, one with multiple :Movies nodes, or a pattern where you may not know which node types are involved or how many, but you want to make sure that all :Movies nodes in the path were released after 2000.

Nodes 2022

NODES 2022, Neo4j Online Education Summit

OnΒ November 16 and 17 for 24 hours across all timezones, youβll learn about best practices for beginners and experts alike.

Neo4j Resources