将实体与 Neo4j 中的适当关系相关联?

Relating an entity to a relationship proper in Neo4j?

我正在尝试使用 Neo4j 来模拟项目、员工和项目角色之间的关系。每个项目都有一个名为 "project manager" 的角色和一个名为 "director" 的角色。我试图在数据模型中完成的是能够说 "for project A, the director is staff X." 就我的目的而言,重要的是 "project"、"staff" 和 "role" 都是实体(而不是属性)。这在 Neo4j 中可能吗?简而言之,Neo4j 中是否可能存在关联实体?在 MySQL 中,这将用具有唯一 ID 列和三个外键列的联结 table 表示,一个分别用于项目、人员和角色,这将使我能够识别它们之间的关系实体作为实体本身。想法?

从概念上讲,Neo4j 图是基于两种主要类型构建的 - 节点和关系。节点可以与关系连接。但是,节点和关系都可以具有属性。

要连接ProjectStaff节点,可以使用以下Cypher语句:

CREATE (p:Project {name:"Project X"})-[:IS_DIRECTOR]->(director:Staff {firstName:"Jane"})

这将创建两个节点。项目节点有一个 Label 类型 Project,职员节点有一个 Label 类型 Staff。在这些节点之间存在 IS_DIRECTOR 类型的关系,表明 Jane 是项目的主管。请注意,关系始终是定向的。

因此,要找到 all 项目的 all 位主管,可以使用以下方法:

MATCH (p:Project)-[:IS_DIRECTOR]->(director:Staff) RETURN director

另一种方法是将属性添加到更一般关系类型:

create (p:Project {name:"Project X"})<-[:MEMBER_OF {role:"Director"}]-(director:Staff {firstName:"Jane"})

这显示了如何向关系添加属性。请注意,第二个示例的关系方向已更改。

要使用基于 属性 的关系查找所有董事,可以使用以下方法:

MATCH (p:Project)<-[:MEMBER_OF {role:"Director"}]-(directors:Staff) RETURN directors

要检索所有角色类型(例如导演),可以使用以下内容:

MATCH 
    (p:Project)-[r]->(s:Staff) 
RETURN 
    r,       // The actual relationship 
    type(r), // The relationship type e.g. IS_DIRECTOR
    r.role   // If properties are available they can be accessed like this

并且,要获得唯一的角色名称列表,可以使用 COLLECTDISTINCT

MATCH 
    (p:Project)-[r]->(s:Staff) 
RETURN 
    COLLECT(DISTINCT type(r)) // Distinct types

或者,对于关系的属性:

MATCH 
    (p:Project)-[r]->(s:Staff) 
RETURN 
    COLLECT(DISTINCT r.role) // The "role" property if that is used

COLLECT returns 列表结果和 DISTINCT 关键字确保列表中没有重复项。

@wassgren 的回答很可靠,值得考虑。

我将提供另一种选择。也就是说,你可以“Reify”表示关系。具体化有点像你把关系变成一个节点。您正在采用抽象关联(员工与项目之间的关系)并将其转变为具体实体(角色)所有其他答案选项基本上涉及两个节点 ProjectStaff,随着它们之间关系的变化。这些方法不具体化角色,而是将其存储为关系的 属性 或标签。

(director:Staff {name: "Joe"})-[:plays]->(r:Role {label:"Director"})-[:member_of]->(p:Project { name: "Project X"});

所以...人们不会直接为项目做出贡献,角色会。人们扮演角色。这具有直观意义。

这种方法的优点是您可以将 "Role" 视为第一个 class 公民,并声明关于它的关系和属性。如果您不将 "Role" 拆分到一个单独的节点中,您将无法将关系挂在该节点之外。此外,如果您向伪装成角色的关系添加额外的属性,您可能最终会混淆 属性 何时适用于该角色,以及何时适用于员工与项目之间的关联.

想知道项目中有哪些人?那只是:

  MATCH (p:Project {label: "Project X"})<-[:member_of]-(r:Role)<-[:plays]-(s:Staff)
   RETURN s;

所以我认为我的建议从长远来看更灵活,但对您来说也可能有点矫枉过正。

考虑一个假设的未来需求:我们希望将角色与技术级别或工作类别相关联。 IE。项目经理应该始终是副总裁或更高级别(愚蠢的例子)。如果你的角色是一段关系,你就不能那样做。如果你的角色是一个合适的节点,你可以。