Reputation: 3009
I have a scenario where I need to calcula a custom degree between the first node (:employee
) where it should only be incremented to another node when this node's label is :natural
or :relative
, but not when it is :legal
.
The thing is I'm having trouble generating this custom degree
property as I needed it.
So far I've tried playing with FOREACH and CASE but had no luck. The closest I got to getting some sort of calculated custom degree is this:
match p = (:employee)-[*5..5]-()
WITH distinct nodes(p) AS nodes
FOREACH(i IN RANGE(0, size(nodes)) |
FOREACH(node IN [nodes[i]] |
SET node.degree = i
))
return *
limit 1
But even this isn't right, as despite having 5 distinct nodes, I get SIZE(nodes) = 6
, as the :legal
node is accounted for twice for some reason.
Does anyone know how to achieve my goal within a single cypher query?
Also, if you know why the :legal
node is account for twice, please let me know. I suspect it is because it has 2 :natural
nodes related to it, but don't know the inner workings that make it appear twice.
More context:
:employee
nodes are, well, employees of an organization
:relative
nodes are relatives to an employee
:natural
nodes are natural persons that may or may not be related to a :legal
:legal
nodes are companies (legal persons) that may, or may not, be related to an :employee
, :relative
, :natural
or another :legal
on an IS_PARTNER
relationship when, in real life, they are part of the board of directors or are shareholders of that company (:legal
).
custom degree
is what I aim to create and will define how close one node is to another given some conditions to this project (specified below).
All nodes have a total_contracts
property that are the total amount of money received through contracts.
The objective is to find any employees with relationships to another node that has total_contracts > 0
and are up to custom degree <= 3
, as employees may be receiving money from external sources, when they shouldn't.
As for why I need this custom degree ignoring the distance when it is a :legal
node, is because we threat companies as the same distance as the natural person that is a partner.
On the illustrated example above, the employee has a son, DIEGO
, that is a shareholder of a company (ALLURE
) and has 2 other business partners (JOSE
and ROSIEL
). When I ask what's the degree of the son to the employee, I should get 1
, as they are directly related; when I ask whats the degree of JOSE
to the employee I should get 2
, as JOSE
is related to DIEGO
through ALLURE
and we shouldn't increment the custom degree when it is a company, only when its a person.
Upvotes: 0
Views: 200
Reputation: 30407
The trick with this type of graph is making sure we avoid paths that loop back to the same nodes (which is definitely going to happen quite a lot because you're using multiple relationships between nodes instead of just one...you may want to make sure this is necessary in your model).
The easiest way to do that is via APOC Procedures, as you can adjust the uniqueness of traversals so that nodes are unique in each path.
So for example, for a specific start node (let's say the :employee has empId:1
just for the sake of mocking up a lookup of the node, we'll calculate a degree for all nodes within 5 hops of the starting node. The idea here is that we'll take the length of the path (the number of hops) - the number of :legal nodes in the path (by filtering the nodes in the path for just :legal nodes, then getting the size of that filtered list).
MATCH (e:employee {empId:1})
CALL apoc.path.expandConfig(e, {minLevel:1, maxLevel:5, uniqueness:'NODE_PATH'}) YIELD path
WITH e, last(nodes(path)) as endNode,
length(path) - size([x in nodes(path) WHERE x:legal]) as customDegree
RETURN e, endNode, customDegree
Upvotes: 1