bigmadwolf
bigmadwolf

Reputation: 3539

How can I include a list of relationships specific to each node returned in the unwind block, in a Neo4j cypher query?

Given a graph where members of an organisation, have one or several relationships to that organisation, and members have incidents, I'm am attempting to return a list of incidents, each including the associated member and a list of their relationships to the organisation.

the graph structure: (org)<-[MEMBER_OF|ADMIN_OF|MANAGER_OF|VISITOR_OF]-(member)-[:HAS]->(incidents)

The query I'm current attempting:

MATCH (incidents:Incident)<-[:HAS]-(member:Person)-[rels]->(org:Org {
  orgId: $orgId
})

WITH org,
     member,
    rels,
     collect(incidents) AS collectedIncidents
UNWIND collectedIncidents AS incident
RETURN incident {
       . *,
         org:properties(org),
         member:properties(member),
         roles: rels
       } AS result
  ORDER BY incident.createdAt DESC
  SKIP $skip
  LIMIT $limit

The result after I created 2 incidents on one member:

[ { member: { 
       createdAt: 1598524633129,
       uuid: '5f430e1b-29d1-49bf-bbcc-fe1b68400378',
    },
    org: { createdAt: 1598524632522,
       name: 'Murder Hornet Inc',
       uuid: '1a69e9a1-4126-4557-b1ff-8f621b25e23d',
       orgId: 'MHI',
       updatedAt: 1598524632522 },
    roles:
     Relationship {
       identity: 167,
       start: 156,
       end: 155,
       type: 'ADMIN_OF',
       properties: {} 
     },
    uuid: '42050b82-f777-4a8a-a063-9bc43e4cf80d',
    createdAt: 1598524637746,
    },
  { member: { 
       createdAt: 1598524633129,
       uuid: '5f430e1b-29d1-49bf-bbcc-fe1b68400378',
     },
    org: { 
       createdAt: 1598524632522,
       name: 'Murder Hornet Inc',
       uuid: '1a69e9a1-4126-4557-b1ff-8f621b25e23d',
       orgId: 'MHI'
     },
    roles:
     Relationship {
       identity: 167,
       start: 156,
       end: 155,
       type: 'ADMIN_OF',
       properties: {} 
      },
     uuid: '21c86703-4f7b-4c67-8344-0131b011b925',
     createdAt: 1598524637746,
    },
  { member: { 
       createdAt: 1598524633129,
       uuid: '5f430e1b-29d1-49bf-bbcc-fe1b68400378',
    },
    org:
     { createdAt: 1598524632522,
       name: 'Murder Hornet Inc',
       uuid: '1a69e9a1-4126-4557-b1ff-8f621b25e23d',
       orgId: 'MHI',
       updatedAt: 1598524632522 },
    roles:
     Relationship {
       identity: 165,
       start: 156,
       end: 155,
       type: 'MEMBER_OF',
       properties: {} },
    uuid: '42050b82-f777-4a8a-a063-9bc43e4cf80d',
    createdAt: 1598524637746
    },
  { member:
     { 
       createdAt: 1598524633129,
       uuid: '5f430e1b-29d1-49bf-bbcc-fe1b68400378',
      },
    org:
     { createdAt: 1598524632522,
       name: 'Murder Hornet Inc',
       uuid: '1a69e9a1-4126-4557-b1ff-8f621b25e23d',
       orgId: 'MHI',
      },
    roles:
     Relationship {
       identity: 165,
       start: 156,
       end: 155,
       type: 'MEMBER_OF',
       properties: {} },
    uuid: '21c86703-4f7b-4c67-8344-0131b011b925',
    createdAt: 1598524637746,
 } 
]

Note that here, I've created 2 incidents on one member, and I get 4 results back. I've also attempted to collect the rels in the WITH statement, which provides some equally odd results.

How can I get a list of unique incidents, including the related member, and the relationships that member has to the org? Ideally I would like just the relationship type in an array (given that there could be one or several relationships to the organisation).

Upvotes: 1

Views: 27

Answers (1)

Skaleb
Skaleb

Reputation: 327

You could use the type() and collect() functions to extract the type of relationship from rels and have them as a list.

collect(DISTINCT type(rels)) will leave you with distinct roles as an array of strings.

You might want to consider ensuring that you have DISTINCT in your collect() of incidents so that you don't have duplicate results when you unwind.

Your query when then look something like the following:

MATCH (incidents:Incident)<-[:HAS]-(member:Person)-[rels]->(org:Org {
  orgId: $orgId
})

WITH org, member, collect(DISTINCT type(rels)) as roles, collect(DISTINCT incidents) AS collectedIncidents
UNWIND collectedIncidents AS incident
RETURN incident {
       . *,
         org:properties(org),
         member:properties(member),
         roles: roles
       } AS result
  ORDER BY incident.createdAt DESC
  SKIP $skip
  LIMIT $limit

Upvotes: 1

Related Questions