I have a starting node, and I'm supposed to find all matching nodes that can be found using 3 different relationship types.
For example: (n1:NodeType1)-[:Use|Realisation|Aggregation]-(n2:NodeType2)
How would I write a query that would search for n2
using the Use
and Realisation
relationships in exclusively one direction, and Aggregation
exclusively in the other? It can be any combination of the three, within 20 hops.
It should be able to cover all combinations. Examples:
(n1)<-[:Use]-()-[:Aggregation]->()<-[:Use]-()<-[:Realisation]-()-[:Aggregation]->(n2)
(n1)-[:Aggregation]->()-[:Aggregation]->()<-[:Use]-(n2)
I currently have this written:
MATCH (n1:`NodeType1`)<-[:`Use`|`Realisation`*0..20]-()-[`Aggregation`*0..20]->(n2:`NodeType2`)
With this I have a problem that after using the 'Aggregation' relationship, it doesn't check for the other two anymore. Another problem is that this could theoretically reach 40 hops, even though I want it limited to a maximum of 20.
Any help in how I could achieve this?
NOTE: Since your maximum path length is 20, any query could take a very long time or run out of memory, depending on your data characteristics.
This query finds every path of up to length 20 using those 3 relationship types in any direction, and then filters for those in which every type points in the required direction (Aggregation
must point right, and the others must point left).
MATCH p=(:NodeType1)-[:Use|Realisation|Aggregation*..20]-(:NodeType2)
WHERE ALL(i IN RANGE(0, LENGTH(p)-1) WHERE NODES(p)[i] = CASE TYPE(RELATIONSHIPS(p)[i])
WHEN 'Aggregation' THEN
STARTNODE(RELATIONSHIPS(p)[i])
ELSE
ENDNODE(RELATIONSHIPS(p)[i]) END
)
RETURN p
This may be faster than approach 1.
This query uses the APOC procedure apoc.path.expandConfig, which has special support for use cases like yours.
MATCH (n:NodeType1)
CALL apoc.path.expandConfig(n, {
relationshipFilter: "<Use|<Realisation|Aggregation>",
labelFilter: ">NodeType2",
minLevel: 1,
maxLevel: 20
}) YIELD path
RETURN path