Imagine a user being part of different groups.
A group can have different roles, and a user can be part of different groups.
He also can have different roles in different groups apart from the membership.
The association of a User, a Group and a Role can be referred to as a HyperEdge.
However, it can be easily modeled in a property graph as a node that captures this n-ary relationship, as depicted below in the U1G2R1
node.
To find out in what roles a user is for a particular groups (here Group2), the following query can traverse this HyperEdge node and provide answers.
Query.
MATCH ({ name: 'User1' })-[:hasRoleInGroup]->(hyperEdge)-[:hasGroup]->({ name: 'Group2' }), (hyperEdge)-[:hasRole]->(role) RETURN role.name
The role of User1
is returned:
Try this query live. create (_0 {`name`:"U1G2R1"}) create (_1 {`name`:"Role2"}) create (_2 {`name`:"Group1"}) create (_3 {`name`:"Group2"}) create (_4 {`name`:"Role1"}) create (_5 {`name`:"Role"}) create (_6 {`name`:"User1"}) create (_7 {`name`:"U1G1R2"}) create (_8 {`name`:"Group"}) create _0-[:`hasRole`]->_4 create _0-[:`hasGroup`]->_3 create _1-[:`isA`]->_5 create _2-[:`canHave`]->_4 create _2-[:`canHave`]->_1 create _2-[:`isA`]->_8 create _3-[:`canHave`]->_1 create _3-[:`canHave`]->_4 create _3-[:`isA`]->_8 create _4-[:`isA`]->_5 create _6-[:`in`]->_2 create _6-[:`in`]->_3 create _6-[:`hasRoleInGroup`]->_0 create _6-[:`hasRoleInGroup`]->_7 create _7-[:`hasRole`]->_1 create _7-[:`hasGroup`]->_2 match ({name: 'User1'})-[:hasRoleInGroup]->(hyperEdge)-[:hasGroup]->({name: 'Group2'}), (hyperEdge)-[:hasRole]->(role) return role.name
Here, find all groups and the roles a user has, sorted by the name of the role.
Query.
MATCH ({ name: 'User1' })-[:hasRoleInGroup]->(hyperEdge)-[:hasGroup]->(group), (hyperEdge)-[:hasRole]->(role) RETURN role.name, group.name ORDER BY role.name ASC
The groups and roles of User1
are returned:
Try this query live. create (_0 {`name`:"U1G2R1"}) create (_1 {`name`:"Role2"}) create (_2 {`name`:"Group1"}) create (_3 {`name`:"Group2"}) create (_4 {`name`:"Role1"}) create (_5 {`name`:"Role"}) create (_6 {`name`:"User1"}) create (_7 {`name`:"U1G1R2"}) create (_8 {`name`:"Group"}) create _0-[:`hasRole`]->_4 create _0-[:`hasGroup`]->_3 create _1-[:`isA`]->_5 create _2-[:`canHave`]->_4 create _2-[:`canHave`]->_1 create _2-[:`isA`]->_8 create _3-[:`canHave`]->_1 create _3-[:`canHave`]->_4 create _3-[:`isA`]->_8 create _4-[:`isA`]->_5 create _6-[:`in`]->_2 create _6-[:`in`]->_3 create _6-[:`hasRoleInGroup`]->_0 create _6-[:`hasRoleInGroup`]->_7 create _7-[:`hasRole`]->_1 create _7-[:`hasGroup`]->_2 match ({name: 'User1'})-[:hasRoleInGroup]->(hyperEdge)-[:hasGroup]->(group), (hyperEdge)-[:hasRole]->(role) return role.name, group.name order by role.name asc
Assume a more complicated graph:
User1
, User2
.
User1
is in Group1
, Group2
, Group3
.
User1
has Role1
, Role2
in Group1
; Role2
, Role3
in Group2
; Role3
, Role4
in Group3
(hyper edges).
User2
is in Group1
, Group2
, Group3
.
User2
has Role2
, Role5
in Group1
; Role3
, Role4
in Group2
; Role5
, Role6
in Group3
(hyper edges).
The graph for this looks like the following (nodes like U1G2R23
representing the HyperEdges):
To return Group1
and Group2
as User1
and User2
share at least one common role in these two groups, the query looks like this:
Query.
MATCH (u1)-[:hasRoleInGroup]->(hyperEdge1)-[:hasGroup]->(group),(hyperEdge1)-[:hasRole]->(role), (u2)-[:hasRoleInGroup]->(hyperEdge2)-[:hasGroup]->(group),(hyperEdge2)-[:hasRole]->(role) WHERE u1.name = 'User1' AND u2.name = 'User2' RETURN group.name, count(role) ORDER BY group.name ASC
The groups where User1
and User2
share at least one common role:
Try this query live. create (_0 {`name`:"U2G2R34"}) create (_1 {`name`:"U1G3R34"}) create (_2 {`name`:"User2"}) create (_3 {`name`:"User1"}) create (_4 {`name`:"Role6"}) create (_5 {`name`:"U1G2R23"}) create (_6 {`name`:"Role4"}) create (_7 {`name`:"Role5"}) create (_8 {`name`:"U2G1R25"}) create (_9 {`name`:"Group1"}) create (_10 {`name`:"Role2"}) create (_11 {`name`:"Group2"}) create (_12 {`name`:"Role3"}) create (_13 {`name`:"Group3"}) create (_14 {`name`:"U1G1R12"}) create (_15 {`name`:"Role1"}) create (_16 {`name`:"U2G3R56"}) create _0-[:`hasGroup`]->_11 create _0-[:`hasRole`]->_12 create _0-[:`hasRole`]->_6 create _1-[:`hasGroup`]->_13 create _1-[:`hasRole`]->_12 create _1-[:`hasRole`]->_6 create _2-[:`hasRoleInGroup`]->_8 create _2-[:`hasRoleInGroup`]->_0 create _2-[:`hasRoleInGroup`]->_16 create _3-[:`hasRoleInGroup`]->_14 create _3-[:`hasRoleInGroup`]->_5 create _3-[:`hasRoleInGroup`]->_1 create _5-[:`hasGroup`]->_11 create _5-[:`hasRole`]->_10 create _5-[:`hasRole`]->_12 create _8-[:`hasGroup`]->_9 create _8-[:`hasRole`]->_10 create _8-[:`hasRole`]->_7 create _14-[:`hasGroup`]->_9 create _14-[:`hasRole`]->_15 create _14-[:`hasRole`]->_10 create _16-[:`hasGroup`]->_13 create _16-[:`hasRole`]->_7 create _16-[:`hasRole`]->_4 match (u1)-[:hasRoleInGroup]->(hyperEdge1)-[:hasGroup]->(group), (hyperEdge1)-[:hasRole]->(role), (u2)-[:hasRoleInGroup]->(hyperEdge2)-[:hasGroup]->(group), (hyperEdge2)-[:hasRole]->(role) where u1.name = 'User1' and u2.name = 'User2' return group.name, count(role) order by group.name ASC
Copyright © 2014 Neo Technology