将实体与Neo4j中的关系联系起来?

时间:2015-01-15 20:09:18

标签: neo4j data-modeling relationships

我试图使用Neo4j来模拟项目,员工和项目角色之间的关系。每个项目都有一个名为"项目经理"和一个名为" director"的角色。我在数据模型中试图完成的是能够说'#34;对于项目A,导演是员工X。"为了我的目的,重要的是"项目","员工"和"角色"是所有实体(与属性相对)。这可能在Neo4j?简单来说,Neo4j中的关联实体是否可能?在MySQL中,这将使用具有唯一id列和三个外键列的联结表来表示,分别用于项目,人员和角色,这将允许我将这些实体之间的关系标识为实体本身。想法?

2 个答案:

答案 0 :(得分:2)

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

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

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

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

因此,要查找所有项目的所有导演,可以使用以下内容:

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返回列表结果,DISTINCT关键字确保列表中没有重复项。

答案 1 :(得分:1)

@ wassgren的答案是可靠的,值得考虑。

我会提供一个额外选项。也就是说,你可以“Reify”这种关系。当您建立关系并将其转换为节点时,Reificiation就是一种。您正在采用抽象关联(员工和项目之间的关系)并将其转换为具体实体(角色)所有其他答案选项基本上涉及两个节点ProjectStaff,他们之间的关系变化。这些方法不会重新定义角色,而是将其存储为关系的属性或标签。

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

所以......人们不直接为项目做贡献,角色也是如此。人们扮演角色。这很直观。

这种方法的优点在于,您可以将“角色”视为一等公民,并断言其关系和属性。如果不将“角色”拆分为单独的节点,则无法将关系挂起节点。此外,如果为伪装成角色的关系添加额外属性,最终可能会混淆属性何时应用于角色,何时应用于职员与项目之间的关联。

想知道项目中谁是谁?那只是:

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

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

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