Hi all.
I am Rob and new to cypher and just working through GraphAcademy's "Intermediate Cypher". In chapter "Working with Cypher Data" is an example for list comprehensions:
MATCH (m:Movie)
RETURN m.title as movie,
[x IN m.countries WHERE x CONTAINS 'USA' OR x CONTAINS 'Germany']
AS country LIMIT 500
The query should only return Movies from Countries USA and Germany but it returns also Movies like "Shanghai Triad (Yao a yao yao dao waipo qiao)" that have "France" and "China" in their countries-List and returns it as an empty country list: [...].
Why does that happen and how can it be avoided?
Kind regard, Rob
Can you post the question's link?
I couldn't find the example you referred to.
Can you paste the query here?
Hi Gary. Thanks for your willingness ;-)
It's an example of the neo4j Graph Academy Course 'Intermediate Cypher'. Within this course it's in Course 'Aggregating Data' at the section 'list comprehensions' what is at about 70% of this Course.
The query is:
MATCH (m:Movie)
RETURN m.title as movie,
[x IN m.countries WHERE x CONTAINS 'USA' OR x CONTAINS 'Germany']
AS country LIMIT 500
referring to the 'Movie-Dataset'. Attached my result.
Kind regards, Robert
I see from the query and the results.
The query will return each movie; it is not filtering the movies with specific languages. Every movie node is returned. The return statement includes the movies’s title and a list comprehension expression aliased to ‘country’. The list comprehension expression is taking the list stored as the movie’s property ‘counties’ and returning a new list that filters out all countries that do not contain the string ‘USA’ or ‘Germany’. The expression always returns a list. In the case where no elements meet the ‘where’ predicate, an empty list will result. That is wha happened with the middle movie.
Dear Gary.
Thank you for your detailed reply. To my understanding, it looks like this query in this form is not able to filter the correct nodes. At least kind of counter intuitive.
Would it be better to use a "where" filter with IN?
Or something like "any" with the list comprehension?
With kind regards,
Robert
If you do want a query the returns only movies that have countries containing ‘USA’ or ‘Germany’, then you need a ‘where’ clause with such a condition. Since the country property is a list, a list predicate is perfect here. You are correct to suggest using ‘any’.
Note, The ‘any’ list predicate is different than list comprehension. The ‘any’ list predicate returns a true or false value, while list comprehension returns a new list.
MATCH (m:Movie)
WHERE any(x IN m.countries WHERE x CONTAINS 'USA' OR x CONTAINS 'Germany')
RETURN m.title as movie
LIMIT 500
Just to recap, the original query did not filter the Movie nodes since there wasn’t a 'where' clause. It returns every Movie node's title and a derived return value based on list comprehension. The list comprehension itself, filtered a movie's list of countries to return a new list consisting of only those countries in the full list that contained the strings 'USA' or "Germany' somewhere in the country's name. The new list will also contain each filtered country's full name, as there is no '|' part to the list comprehension to transform each element of the movie's country list to a new value.
Example of list comprehension without transformation:
Example of list comprehension with a transformation step:
1 Like
Hi Gary.
Very sophisticated response. Thanks a lot for your time, Ninja
Kind regards, Robert
1 Like
Great answer, thanks @glilienfield !
Hi Gary and Adam!
The text in the GraphAcademy says:
List comprehension enables you to extract values from an existing list. You can create a list by evaluating an expression that tests for list inclusion. In addition, you can modify the values returned in the list.
For me that means in short: With a List comprehension - as the name says - I can work on lists BUT NOT on NODES (e.g. to filter). So the provided result is correct 