-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Organization Structure Representation
Problem
Currently, there is no defined mechanism to store the organizational structure for entities such as Ministries and Departments. Because of this limitation, it is difficult to represent relationships between organizational roles and the people assigned to them.
For example, we need to represent:
- The hierarchical structure of an organization (e.g., Minister → Secretary → Teams).
- The people assigned to specific roles within that structure.
- Efficient queries to retrieve subsets (subgraphs) of the organizational hierarchy.
Without a clear structure, managing these relationships and querying them becomes complex and inefficient.
Proposed Solution
The proposed approach introduces a dedicated organization node for each entity (e.g., Ministry or Department). This node represents the root of the organizational structure.
All roles or positions within that organization are connected to this organization node through hierarchical relationships. Instead of directly connecting people to the organization, people are assigned to specific roles within the structure.
This design allows us to:
- Clearly represent hierarchical relationships between roles.
- Assign people to roles dynamically.
- Efficiently query portions of the organization as subgraphs.
Organizational Structure Model
The following diagram illustrates the proposed structure.
flowchart TD
A((Minister Entity)) --AS_ORG--> B((Minister Org))
B --OVERSEES--> C((Minister Role))
C --OVERSEES--> D((Secretary Role))
D --OVERSEES--> E((Team))
F((Person 1)) --AS_ROLE--> E
G((Person 2)) --AS_ROLE--> C
H((Person 3)) --AS_ROLE--> D
E --OVERSEES--> I((Role 1))
I --OVERSEES--> J((Role 2))
L((Person 4)) --AS_ROLE--> J
Tested Neo4j example
Create the Graph
// 1. Create the Core Nodes (as defined in your previous step)
CREATE (min1:Organisation {Name: "Minister_1", Id: "min_id_1", Created: datetime.realtime(), MinorKind: "cabinetMinister"})
CREATE (dep1:Organisation {Name: "Department_1", Id: "dep_id_1", Created: datetime.realtime(), MinorKind: "department"})
CREATE (minOrg:Organisation {Name: "Minister_1_org", Id: "min_id_1_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
// 2. Create the Roles, Boards, and Teams
CREATE (mRole1:Organisation {Name: "ministerRole_1", Id: "minrole_id_1_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (mRole2:Organisation {Name: "ministerRole_2", Id: "minrole_id_2_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (mRole3:Organisation {Name: "ministerRole_3", Id: "minrole_id_3_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (sRole1:Organisation {Name: "secretaryRole_1", Id: "secrole_id_1_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (sRole2:Organisation {Name: "secretaryRole_2", Id: "secrole_id_2_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (brd1:Organisation {Name: "Board_1", Id: "board_id_1_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (brd2:Organisation {Name: "Board_2", Id: "board_id_2_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (brd3:Organisation {Name: "Board_3", Id: "board_id_3_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (tm1:Organisation {Name: "Team_1", Id: "team_id_1_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (tm2:Organisation {Name: "Team_2", Id: "team_id_2_org", Created: datetime.realtime(), MinorKind: "orgStructure"})
// 3. Create New Role Nodes for Teams and Secretaries
CREATE (tm1RoleA:Organisation {Name: "Lead Analyst", Id: "role_tm1_a", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (tm1RoleB:Organisation {Name: "Junior Developer", Id: "role_tm1_b", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (tm2RoleA:Organisation {Name: "Project Coordinator", Id: "role_tm2_a", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (secStaff1:Organisation {Name: "Executive Assistant", Id: "role_sec1_a", Created: datetime.realtime(), MinorKind: "orgStructure"})
CREATE (secStaff2:Organisation {Name: "Scheduling Officer", Id: "role_sec2_a", Created: datetime.realtime(), MinorKind: "orgStructure"})
// 4. Create Person nodes
CREATE (p1:Person {Name: "Person_1", Id: "per_1_org", Created: datetime.realtime(), MinorKind: "citizen"})
CREATE (p2:Person {Name: "Person_2", Id: "per_2_org", Created: datetime.realtime(), MinorKind: "citizen"})
CREATE (p3:Person {Name: "Person_3", Id: "per_3_org", Created: datetime.realtime(), MinorKind: "citizen"})
CREATE (p4:Person {Name: "Person_4", Id: "per_4_org", Created: datetime.realtime(), MinorKind: "citizen"})
CREATE (p5:Person {Name: "Person_5", Id: "per_1_org", Created: datetime.realtime(), MinorKind: "citizen"})
CREATE (p6:Person {Name: "Person_6", Id: "per_2_org", Created: datetime.realtime(), MinorKind: "citizen"})
// 5. Establish Relationships with Temporal Properties
// Minister to Department and Org Root
CREATE (min1)-[:AS_DEPARTMENT {Id: "min_dep_1", CreatedDate: datetime.realtime()}]->(dep1)
CREATE (min1)-[:AS_ORG {Id: "min_min_org", CreatedDate: datetime.realtime()}]->(minOrg)
// Minister 1 Org overseeing Boards
CREATE (minOrg)-[:OVERSEES {Id: "min_org_brd_1", CreatedDate: datetime.realtime()}]->(brd1)
CREATE (minOrg)-[:OVERSEES {Id: "min_org_brd_2", CreatedDate: datetime.realtime()}]->(brd2)
// Example of a terminated board oversight
CREATE (minOrg)-[:OVERSEES {Id: "min_org_brd_3", CreatedDate: datetime.realtime(), Terminated: datetime("2025-12-31T23:59:59")}]->(brd3)
// Board 1 overseeing Minister Roles
CREATE (brd1)-[:OVERSEES {Id: "brd_min_1", CreatedDate: datetime.realtime()}]->(mRole1)
CREATE (brd1)-[:OVERSEES {Id: "brd_min_2", CreatedDate: datetime.realtime()}]->(mRole2)
CREATE (brd1)-[:OVERSEES {Id: "brd_min_3", CreatedDate: datetime.realtime()}]->(mRole3)
// Minister 1 overseeing Secretary Roles
CREATE (minOrg)-[:OVERSEES {Id: "min_sec_1", CreatedDate: datetime.realtime()}]->(sRole1)
CREATE (minOrg)-[:OVERSEES {Id: "min_sec_2", CreatedDate: datetime.realtime()}]->(sRole2)
// Boards overseeing Teams
CREATE (brd1)-[:OVERSEES {Id: "brd_tm_1", CreatedDate: datetime.realtime()}]->(tm1)
CREATE (brd2)-[:OVERSEES {Id: "brd_tm_1", CreatedDate: datetime.realtime()}]->(tm2)
// 6. Establish Final Leaf Relationships
// Teams overseeing roles
CREATE (tm1)-[:OVERSEES {Id: "tm1_role_a", CreatedDate: datetime.realtime()}]->(tm1RoleA)
CREATE (tm1)-[:OVERSEES {Id: "tm1_role_b", CreatedDate: datetime.realtime()}]->(tm1RoleB)
CREATE (tm2)-[:OVERSEES {Id: "tm2_role_a", CreatedDate: datetime.realtime()}]->(tm2RoleA)
// Secretaries overseeing roles
CREATE (sRole1)-[:OVERSEES {Id: "sec_sec_staff_1", CreatedDate: datetime.realtime()}]->(secStaff1)
CREATE (sRole2)-[:OVERSEES {Id: "sec_sec_staff_2", CreatedDate: datetime.realtime()}]->(secStaff2)
// 7. Assign persons with tenure properties
CREATE (p1)-[:AS_ROLE {Id: "p1_sec_staff_1", CreatedDate: datetime.realtime()}]->(secStaff1)
CREATE (p2)-[:AS_ROLE {Id: "p2_sec_staff_2", CreatedDate: datetime.realtime()}]->(secStaff2)
CREATE (p3)-[:AS_ROLE {Id: "p3_min_role_1", CreatedDate: datetime.realtime()}]->(mRole1)
// Example: Person 4 has left their role
CREATE (p4)-[:AS_ROLE {Id: "p4_min_role_2", CreatedDate: datetime("2024-01-01"), Terminated: datetime.realtime()}]->(mRole2)
CREATE (p5)-[:AS_ROLE {Id: "p5_sec_role_1", CreatedDate: datetime.realtime()}]->(sRole1)
Query on the graph
MATCH p = (n:Organisation {Name: "Minister_1_org"})-[:OVERSEES|AS_ROLE*]-(sub)
WHERE ANY(m IN nodes(p) WHERE m.Name = "Board_1")
RETURN p