Cypher: Neighbours of which all neighbours satisfy an inequality - cypher

Let's say you have a database that satisfies the following scheme:
(person {name:string, budget:int})
(person)-[:FRIEND]-(person)
How would one query the following in Cypher?
"Give all friends of Alice of whom holds that ALL their friends have a budget that is greater than 100."

You can use the following query in Cypher for this:
MATCH (alice {name:"Alice"})
MATCH (alice)-[:FRIEND]-(f)
MATCH (f)-[:FRIEND]-(person)
WITH f, collect(person) as friends
WHERE ALL(x in friends WHERE x.budget > 100 )
RETURN f, friends

Related

I would to find the node that has the highest number of attributes

i am new in cypher. imagine that each person node defines by name and id, has some skills which are defined by id and vary from : skill1, skill2, skill3, skill4, skill5, skills6). I would like to return the person that has the highest number of skills. note that the same person id can have more that id in the skill node.
my query does not work can someone help me please
match (n:person)-[:HAS]->(f:skills)
with n,f
unwind keys(f)as key
with n,f, count(key) as p
with n, max(p) as s
where count(key)=s
return distinct n

How to select in SQL

I have 2 tables I am working with, one is movie_score which contains an id, name, and score. I have another table that is movie_cast which contains mid, cid, and name. Mid is movie id and cid is cast id. the problem I must do is as follows:
Find top 10 (distinct) cast members who have the highest average movie scores. The output list must be sorted by score (from high to low), and then, by cast name in alphabetical order, if/when they have the same average score. The search must NOT include: (a) movies with scores lower than 50 AND (b) cast members who have appeared in less than 3 movies (again, only counting the number of appearances in movies with scores of at least 50). (Expected Output: cid, cname, average score)
I have tried to put the command together but so far this is all I was able to get:
SELECT DISTINCT movie_cast.cid, movie_cast.cname, FROM movie_score INNER JOIN movie_cast ON movie_score.id=movie_cast.mid ORDER BY cname LIMIT 10;
movie-name-score.txt goes with movie_score:
Example of .txt file
9,"Star Wars: Episode III - Revenge of the Sith 3D",80
24214,"The Chronicles of Narnia: The Lion, The Witch and The Wardrobe",76
1789,"War of the Worlds",74
10009,"Star Wars: Episode II - Attack of the Clones 3D",67
771238285,"Warm Bodies",-1
770785616,"World War Z",-1
771303871,"War Witch",89
771323601,"War of the Worlds the True Story",-1
movie-cast.txt goes with movie_cast:
Example:
9,162652153,"Hayden Christensen"
9,162652152,"Ewan McGregor"
9,418638213,"Kenny Baker"
9,548155708,"Graeme Blundell"
9,358317901,"Jeremy Bulloch"
9,178810494,"Anthony Daniels"
9,770726713,"Oliver Ford Davies"
9,162652156,"Samuel L. Jackson"
9,162655731,"James Earl Jones"
I expect to have an output something like:
162655731,"James Earl Jones",average score of the movies they have been in
Does anyone know the best way to create this command?

Does Cypher has functions like Group By?

I am new to Neo4j and wondering if Cypher has functions like GROUP BY in SQL.
Here is my code:
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
RETURN m.title AS movie, p.name AS actor
Here is my result from above query:
movie actor
"The Matrix" "Emil Eifrem"
"The Matrix" "Carrie-Anne Moss"
"The Matrix" "Keanu Reeves"
"The Matrix Reloaded" "Hugo Weaving"
"The Matrix Reloaded" "Laurence Fishburne"
"The Matrix Revolutions" "Hugo Weaving"
"The Matrix Revolutions" "Laurence Fishburne"
Here is the result I want to have:
movie actor num_of_actors
"The Matrix" "Emil Eifrem" 3
"The Matrix" "Carrie-Anne Moss" 3
"The Matrix" "Keanu Reeves" 3
"The Matrix Reloaded" "Hugo Weaving" 2
"The Matrix Reloaded" "Laurence Fishburne" 2
"The Matrix Revolutions" "Hugo Weaving" 2
"The Matrix Revolutions" "Laurence Fishburne" 2
Basically I would like to have the number of actors played in each movie together with the original results.
Thanks in advance
You'll want to review the aggregation functions, which you can use within a WITH clause to do grouping.
For example, if you wanted to group the actor names with each movie, you could do this:
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WITH m, collect(p.name) as actors
RETURN m.title AS movie, actors
That said, there are some shortcuts we can do here since you're asking about the total number of actors per movie (see our knowledge base article on using degree counts from a node instead of doing expansions).
If you wanted to keep a separate row per actor, but also have the number of actors, since we know :ACTED_IN relationships will never go to the same actor more than once, we can get the degree of :ACTED_IN relationships incoming to each :Movie node to get our count. For best performance, get the degree before you expand out to actors:
MATCH (m:Movie)
WITH m, m.title as title, size((m)<-[:ACTED_IN]-()) as num_of_actors
MATCH (p:Person)-[:ACTED_IN]->(m)
RETURN title, p.name as actor, num_of_actors

How can I query an edge property by value?

I'm using OrientDB (Community-2.0.9) and have two vertices: Person and University and one edge: isStudent. The edge isStudent has the property 'mark' as float. Person --isStudent--> University.
Now I want to select all persons, where the mark is greater than 3.0, but I got no results, but if I query for equality I got two results.
Do you have any ideas how to solve this?
Queries:
SELECT FROM PERSON WHERE out_isStudent.mark = 3.4 --> two results
SELECT FROM PERSON WHERE out_isStudent.mark > 3.0 --> no results
If you:
select out_isStudent.mark from Person
you see that it returns the list [3.4] instead of 3.4
The query that should not work is the first since you're comparing [3.4] == 3.4
You can achieve what you want with:
select from Person where out_isStudent[0].mark > 3

Grails SQL match criteria

My case are searching people over interest types, age, activities and so on. And at least one information must match and show the result.
For example: It must be a woman within 25-31 years old range and (optionally) I would like to know people that speak: english, german and italian, and my interests are: going to party, people that speak my language, do activities outside. Another profile create is almost the same with some information are equals.
Age and sex are the main lock of matching the criteria. And others are optional, the example above, if a person speak japanese and italian and must be a woman within 25-31 years old, show in results.
But I'm stuck where I want to find people that has speak any of 3 language, or interests, how can I loop through it(I have an array)? Should I get all results and then make a method the compare? Or should I use createCriteria()
My code is static:
def e = User.executeQuery("from User as u where (u.profile.sexType = 2 and u.profile.ageRangeType = 2) > (select Profile as p where ")
My english is not the best.
Try grouping by the other criteria and doing a count on the languages column. Then you use a HAVING clause to find those who know more then 3 languages.
SELECT User, COUNT (Languages)
FROM Profile
WHERE (Other user criteria)
GROUP BY User
HAVING COUNT (Languages) > 2