来自Training的Neo4j cypher查询

时间:2014-01-31 14:54:51

标签: neo4j cypher

我刚刚在http://www.neo4j.org/learn/online_course完成了培训,并对实验室的答案提出了几个问题。

第一部分来自第2课中的高级图表实验室。(没有给出答案,也没有在图表小部件中验证)

问题是:推荐基努·里维斯应该合作的3位演员(但没有)。提示是你基本上应该选择与电影有ACTED_IN关系的三个人,而基本也没有ACTED_IN。

该图具有具有ACTED_IN关系和DIRECTED关系的Person节点和Movie节点。

我想出了这个:

MATCH (a:Person)-[:ACTED_IN]->(movie:Movie)
WHERE NOT (:Person {name:"Keanu Reeves"})-[:ACTED_IN]->(movie)
RETURN a, count(movie)
ORDER BY count(movie) DESC
LIMIT 3

但是我无法分辨是否实际上排除了同一部电影或者仅仅是keanu reeves(因为返回的演员没有出现在Keanu的电影中,但他们可能已经被归还了。

3 个答案:

答案 0 :(得分:3)

到目前为止,我找到了两个解决方案。

1:推荐最忙碌的演员基努·里维斯没有采取行动。

MATCH (p:Person)-[:ACTED_IN]->(m)
WHERE p.name <> 'Keanu Reeves'
AND NOT (p)-[:ACTED_IN]->()<-[:ACTED_IN]-(:Person{name:'Keanu Reeves'})
RETURN p.name, count(m) AS rating
ORDER BY count(m) DESC
LIMIT 3;

哪个收益

p.name          | rating
--------------------------
Tom Hanks       | 12
Meg Ryan        | 5
Cuba Gooding Jr.| 4

2:推荐演员keanu Reeves的合作明星与最多的合作

MATCH (f:Person)-[:ACTED_IN]->(m)<-[:ACTED_IN]-(c:Person),
(k:Person{name:'Keanu Reeves'})
WHERE c.name <> 'Keanu Reeves'
AND (f)-[:ACTED_IN]->()<-[:ACTED_IN]-(k)
AND NOT (c)-[:ACTED_IN]->()<-[:ACTED_IN]-(k)
RETURN c.name, count(c) AS  Rating
ORDER BY Rating desc
LIMIT 3;

哪个收益

p.name          | rating
--------------------------
Danny DeVito    | 2
J.T. Walsh      | 2
Tom Hanks       | 2

答案 1 :(得分:1)

今天我遇到了这个问题,在这里我做了什么

MATCH (keanu:Person)-[:ACTED_IN]->(movie),
      (playedwith:Person)-[:ACTED_IN]->(movie), 
      (playedwith)-[t:ACTED_IN]->(othermovie),
      (other:Person)-[:ACTED_IN]->(othermovie)
WHERE keanu.name = "Keanu Reeves"
      AND NOT (other)-[:ACTED_IN]->(movie)
      AND NOT (keanu)-[:ACTED_IN]->(othermovie)
RETURN other.name
      ,collect(DISTINCT othermovie)
      ,collect(DISTINCT playedwith)
      ,count(DISTINCT playedwith)
ORDER BY count(DISTINCT playedwith)desc
LIMIT 3

因为有这么多的Distict我不喜欢它,但结果如下:

other.name    | collect(DISTINCT othermovie) | collect(DISTINCT playedwith)        | count(DISTINCT playedwith)
-----------------------------------------------------------------------------------------------------------------------------
Tom Hanks     | ["Cloud Atlas",              | ["Hugo Weaving","Charlize Theron"]  | 2
              |  "That Thing You Do"]        |
Tom Cruise    | ["A Few Good Men"]           | ["Jack Nicholson"]                  | 1
Robin Williams| ["The Birdcage"]             | ["Gene Hackman"]                    | 1

答案 2 :(得分:1)

所以我找到了两种看似不错的方式。第一个发现那些拥有最多“ACTED_IN相同电影”路径的人,原来的人不是基努·里维斯与“ACTED_IN同一部电影”关系的人。

第二个发现某个人没有ACTED_IN与Keanu Reeves一起拍摄电影,但却被大多数电影中的人所订购。

当然,最简单的方法是在所有分享这种关系的演员之间创建一个“WORKED_WITH”关系,然后搜索每个人Keanu没有WORKED_WITH,但这会让我猜错的乐趣。

第一个非常简单并且看起来非常准确的解决方案:

MATCH (a:Person {name:"Keanu Reeves"})-[:ACTED_IN]->(:Movie)<-[:ACTED_IN]-(b:Person)
WITH collect(b.name) AS FoF
MATCH (c:Person)-[:ACTED_IN]->(:Movie)<-[:ACTED_IN]-(d:Person)
WHERE not c.name IN FoF AND c.name <> "Keanu Reeves"
RETURN distinct c.name, count(distinct d)
ORDER BY count(distinct d) desc
limit 3

它返回:

c.name          | count(distinct d)
-------------------------------
Tom Hanks       |    34
Cuba Gooding Jr.|    24
Tom Cruise      |    23

其中d是c的人数为“ACTED_IN”的人数。


编辑添加:

在回答之后,我使用他们更简化的查询方法来提出这个:

MATCH (a:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(b:Person)
WHERE a.name <>'Keanu Reeves' 
AND NOT (a)-[:ACTED_IN]->()<-[:ACTED_IN]-(b:Person {name:'Keanu Reeves'})
RETURN a.name, count(Distinct b) AS Rating
ORDER BY Rating DESC
LIMIT 3

返回与上面相同的内容。


或者我将这个用于大多数电影中工作的人:

MATCH (a:Person {name:"Keanu Reeves"})-[:ACTED_IN]->(:Movie)<-[:ACTED_IN]-(b:Person)
WITH collect(b.name) AS FoF
MATCH (c:Person)-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(d:Person)
WHERE not c.name IN FoF AND c.name <> "Keanu Reeves"
RETURN distinct c.name, count(distinct m)
ORDER BY count(distinct m) desc
limit 3

返回:

c.name           |  count(distinct m)
-------------------------------------------
Tom Hanks        |  11
Meg Ryan         |  5
Cuba Gooding Jr. |  4

其中m是他们工作的电影数量。