【问题标题】:Neo4j cypher query from Training来自 Training 的 Neo4j 密码查询
【发布时间】:2014-01-31 14:54:51
【问题描述】:

我刚刚在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

但我不知道这是否真的排除了同一部电影或只是基努·里维斯(因为返回的演员没有出现在基努的电影中,但他们可能已经被返回了。

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

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

    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:推荐基努·里维斯合作过最多的演员

    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
    

    【讨论】:

    • 现在我正在阅读它们,这很有意义。结果与我的解决方案相似,但语法更简单。
    • 你的语法比我想出的要干净得多(我的管道查询带有 NOT IN 语句)。我修改了我的第一个(显示没有与 Keanu 合作过的演员以及最多的合作演员(朋友))以匹配您的查询风格并且更喜欢它。
    【解决方案2】:

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

    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
    

    【讨论】:

    • 我想你也可以根据其他电影进行计数,它会给出不同的结果,Tom hanks、Danny Devito 和 J.T.沃尔什在那些情况下
    • Tom Hanks 实际上已经与超过 2 个人合作过。请参阅我的新答案。
    【解决方案3】:

    所以我找到了 2 种看起来不错的不同方式。第一个查找具有最多“ACTED_IN 同一部电影”路径的人,而原始人不是与基努·里维斯有“ACTED_IN 同一部电影”关系的人。

    第二个查找没有与基努·里维斯合作的电影 ACTED_IN 的人,但按出演电影最多的人排序。

    当然,最简单的方法是在所有共享此关系的演员之间创建“WORKED_WITH”关系,然后搜索所有基努没有 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”的人数。


    编辑添加:

    在 's answer 之后,我使用了他们更精简的查询方法来提出这个:

    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 是他们参与过的电影数量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多