【问题标题】:How to return all movies with the same crew in neo4j?如何在 neo4j 中返回具有相同工作人员的所有电影?
【发布时间】:2017-12-05 13:00:14
【问题描述】:

由于我是 neo4j 的新手,我目前正在尝试使用 neo4j 电影数据库示例。

我想知道比较子图和关系的最佳方法是什么,例如,如何让所有电影的工作人员都相同。

基于 stackoverflow 上的其他问题,我让它返回所有特定演员一起出演的电影:

WITH ['Tom Hanks', 'Meg Ryan'] as names
MATCH (p:Person)
WHERE p.name in names
WITH collect(p) as persons
WITH head(persons) as head, tail(persons) as persons
MATCH (head)-[:ACTED_IN]->(m:Movie)
WHERE ALL(p in persons WHERE (p)-[:ACTED_IN]->(m))
RETURN m.title

但是,我如何在不指定演员姓名的情况下检索具有相同演员的电影?

【问题讨论】:

    标签: neo4j cypher graph-databases


    【解决方案1】:

    一些可能更有效的替代方法(使用 PROFILE 检查):

    只从电影到演员匹配一次,然后收集它们并 UNWIND 生成叉积所需的次数,然后过滤并比较。这使您不必多次访问数据库,因为您所需要的只是从第一次匹配中获得的数据。我将借用布鲁诺的查询并稍微调整一下。

    // match the first movie and all its actors
    match (m1:Movie)<-[:ACTED_IN]-(a1:Person)
    // order actors by name
    with m1, a1 order by a1.name
    // store ordered actors into actors1 variable
    with m1, collect(a1) as actors1
    // collect this data into a single collection
    with collect({m:m1, actors:actors1}) as data
    // generate cross product of the data
    unwind data as d1
    unwind data as d2
    with d1, d2
    // prevent comparison against the same movie, or the same pairs in different orders
    where id(d1.m) < id(d2.m) and d1.actors = d2.actors
    // return movies that have the same actors
    return d1.m, d2.m
    

    或者,您可以按演员对电影进行分组,并仅返回相应分组的电影:

    // match the first movie and all its actors
    match (m1:Movie)<-[:ACTED_IN]-(a1:Person)
    // order actors by name
    with m1, a1 order by a1.name
    // store ordered actors into actors1 variable
    with m1, collect(a1) as actors1
    // group movies with their sets of actors
    with collect(m1) as movies, actors1
    // only interested in where multiple movies have the same actor sets
    where size(movies) > 1
    // return the collection of movies with the same actors
    return movies
    

    这里的第二个查询可能更好,因为您可以获取所有具有相同演员阵容的电影,而不是每行获取对。

    【讨论】:

      【解决方案2】:

      这个查询应该可以工作:

      // match the first movie and all its actors
      match (m1:Movie)<-[:ACTED_IN]-(a1:Person)
      // order actors by name
      with m1, a1 order by a1.name
      // store ordered actors into actors1 variable
      with m1, collect(a1) as actors1
      // match the second movie and all its actors
      match (m2:Movie)<-[:ACTED_IN]-(a2:Person)
      // avoid match the same movie with where id(m1) > id(m2)
      where id(m1) > id(m2)
      // order actors of m2 by name
      with m1, m2, actors1, a2 order by a2.name
      // store ordered actors of m2 into actors2 variable
      // pass to the next context only when the ordered arrays (actors1 and actors2) are equals
      with m1, m2, actors1, collect(a2) actors2 where actors1 = actors2
      // return movies that have the same actors
      return m1, m2 
      

      使用电影数据库 (:play movie graph),此查询产生以下输出:

      ╒══════════════════════════════════════════════════════════════════════╤══════════════════════════════════════════════════════════════════════╕
      │"m1"                                                                  │"m2"                                                                  │
      ╞══════════════════════════════════════════════════════════════════════╪══════════════════════════════════════════════════════════════════════╡
      │{"title":"The Matrix Revolutions","tagline":"Everything that has a beg│{"title":"The Matrix Reloaded","tagline":"Free your mind","released":2│
      │inning has an end","released":2003}                                   │003}                                                                  │
      └──────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────┘
      

      【讨论】:

      • 看起来不错,但不应该出现在列表中,因为它与其他两部矩阵电影有相同的演员;)
      • @mian 对不起,我不明白。你能告诉我更多细节吗?
      • 我想获取所有具有相同工作人员(演员)的电影名称,您的解决方案看起来相当不错,但电影图表包含三个矩阵电影,矩阵、重装矩阵和矩阵革命,所以我想要的结果是“The Matrix - The Matrix Reloaded”、“The Matrix - The Matrix Revolution”、“The Matrix Reloaded - The Matrix Revolution”表示所有可能的元组。希望这会有所帮助。
      • @mian 运行此查询:match (m:Movie)&lt;-[:ACTED_IN]-(p:Person) where m.title =~ '..*Matrix.*' return m, collect(p),您将看到“黑客帝国 - 欢迎来到现实世界”有不同的工作人员。
      • @BrunoPeres 请记住,您对第二部电影及其演员的处理只是重复了您已经为第一部电影所做的处理,并且这样做了不必要的次数(因为您是执行相同的操作 * # of movies - # of movies)
      猜你喜欢
      • 1970-01-01
      • 2020-01-04
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多