Graphdb/Neo4j 与另一个关系的关系,或与 3 个节点的关系

Graphdb/Neo4j relationship to another relationship, or relationship with 3 nodes

我想在 Neo4j 中制作 IMDB 的 characters/roles 结构。我需要标签 PersonMovieCharacterCharacter,因为一个角色可以出现在多部电影中,由不同的人扮演。

没有Character,很简单:

(Person)-[:PLAYS_IN]->(Movie)

但是 PLAYS_IN 是一个 Character,所以它会是这样的:

(Person)-[:PLAYS_AS]->(Character)-[:PLAYS_IN]->(Movie)

但这不起作用,因为它没有直接的 Person-Movie 关系。没有它,所有扮演过彼得帕克的人都会出现在每部有彼得帕克的电影中。

既要有人影关系,又要有人影人物关系。如何?这可能行得通,但这太糟糕了:

(Person)-[:PLAYS_IN {uuid}]->(Movie), (Character {uuid})

因为现在我正在创建自己的外键关系。这是非常ungraphdb。但它有效:

MATCH (p:Person)-[r:PLAYS_IN]->(m:Movie), (c:Character)
WHERE c.uuid = r.uuid
RETURN p, c, m

通过构建笛卡尔积 =( 非常像 RDBMS,但不是非常 graphdb。而且我无法查询 Character-MovieCharacter-Person,因为那不是真正的关系。

如何在 Neo4j 中使用 3 个外键 (movie_id, character_id, person_id) 创建 RDBMS link table?

编辑 1
RDBMS 等效项:

movies (id, title)                         # e.g. Dragon Tattoo, or Spider's Web
people (id, name)                          # e.g. Rooney Mara, or Claire Foy
characters (id, name)                      # e.g. Lisbeth Salander
roles (movie_id, person_id, character_id)  # 2 rows with 1 distinct character_id

ActorMovie 之间的关系成为 rich relationship,其中 Actor PLAYED_INMovie 扮演特定的 RoleRole作为一个单独的实体(关系实体)实现,具有自己的属性,只有当ActorMovie之间的关系存在时才成为一个实体。

@NodeEntity
public class Actor {
    Long id;
    @Relationship(type="PLAYED_IN") private Role playedIn;
}

@RelationshipEntity(type = "PLAYED_IN")
public class Role {
    @Id @GeneratedValue   private Long relationshipId;
    @Property  private String title;
    @StartNode private Actor actor;
    @EndNode   private Movie movie;
}

@NodeEntity
public class Movie {
    private Long id;
    private String title;
}

(来自上述 link 的令牌)

您的问题已由 hypergraphs 解决。但是由于 neo4j 不支持超图,您需要对它们进行建模。例如:

CREATE (P1:Person {name: 'Tobey Maguire'})
CREATE (P2:Person {name: 'Nicholas Hammond'})
CREATE (CW1:CreativeWork {name: 'Spider-Man'})
CREATE (CW2:CreativeWork {name: 'The Amazing Spider-Man (TV Series)'})
CREATE (CH:Character {name: 'Spider-Man'})

CREATE (A1:Role)
CREATE (A2:Role)

CREATE (P1)-[:PLAYS_AS]->(A1)
CREATE (A1)-[:HAS_CHARACTER]->(CH)
CREATE (A1)-[:PLAYS_IN]->(CW1)

CREATE (P2)-[:PLAYS_AS]->(A2)
CREATE (A2)-[:HAS_CHARACTER]->(CH)
CREATE (A2)-[:PLAYS_IN]->(CW2)