Hi folks.
Pretty much a n00b and I have tried searching for questions about relationships but nothing seems relevant which suggests I'm not phrasing my search correctly
Hopefully, the title is self-explanatory.
Is there a pattern for matching a node that has not or another relationship from a set, but ALL the relationships from a set (actually only 2)?
I'm modelling software vulnerabilities and I'd like to find github repos that have both :hasSCAFindings and :hasSASTDefect relationships. If I wanted one or the other the [:x|y|z] approach would do what I want but I don't know where to go on this one.
I'm sure that like many things, it's simple once you know how, so any advice is greatly appreciated.
Many thanks!
see Predicate functions - Cypher Manual and the usage of 'ANY'.
The below example, as I understand your question, should report all nodes which have 2 relationships, namely REL1
and REL2
// 1. create 3 nodes
create (n:N {id:1});
create (n:N {id:2});
create (n:N {id:3});
// create 2 relationships REL1 and REL2 for node w id=1
match (n:N {id:1}),(n2:N {id:2}) create (n)-[:REL1]->(n2);
match (n:N {id:1}),(n2:N {id:2}) create (n)-[:REL2]->(n2);
// create 1 relationship REL1 for node w id=2
match (n:N {id:2}),(n2:N {id:3}) create (n)-[:REL1]->(n2);
// create 2 relationships REL1 and REL3 for node w id=3
match (n:N {id:3}),(n2:N {id:2}) create (n)-[:REL1]->(n2);
match (n:N {id:3}),(n2:N {id:2}) create (n)-[:REL3]->(n2);
// create 5 relationships REL1, REL2, REL3, REL4, REL5 for node w id=2
match (n:N {id:2}),(n2:N {id:1}) create (n)-[:REL1]->(n2);
match (n:N {id:2}),(n2:N {id:1}) create (n)-[:REL2]->(n2);
match (n:N {id:2}),(n2:N {id:1}) create (n)-[:REL3]->(n2);
match (n:N {id:2}),(n2:N {id:1}) create (n)-[:REL4]->(n2);
match (n:N {id:2}),(n2:N {id:1}) create (n)-[:REL5]->(n2);
// show all start node, terminating node and the relationships between 2 node
match (n)-[r]->(n2) return n,n2,collect(r);
// report only those nodes which have a REL1 and a REL2
match (n)-[r]->() with n,collect(type(r)) as allRels
where ANY (x IN allRels WHERE x = 'REL1' ) AND
ANY (x IN allRels WHERE x ='REL2')
return n,allRels;
and if you only want only thos node where they only have 2 relationships and they are REL1
and REL2
then
match (n)-[r]->() with n,collect(type(r)) as allRels
where size(allRels)=2 and
ANY (x IN allRels WHERE x = 'REL1' ) AND
ANY (x IN allRels WHERE x ='REL2') return n,allRels;
Tell me if i'm wrong:
MATCH ()<-[:hasSCAFindings]-(ghr:GithubRepo)-[:hasSASTDefect]->()
RETURN ghr
That's it, I don't think it has to be more complicated then that.
Yeah. My response may have over complicated
Over-complicated or not, it worked and it's a useful example of something that I would never have stumbled across on my own, so thank you for taking the time to reply
Thanks Tard! This also works and is a lot simpler to get my head around. Because of the way my if structured my data all my examples so far have just single directed relationships. I think that got me into thinking in a particular way, so this is an excellent example for me.
As the writing language is only left to right, you can add more then two relations to your ghr node like this if needed:
MATCH ()<-[:hasSCAFindings]-(ghr:GithubRepo)-[:hasSASTDefect]->(), (ghr)-[:hasNewRelation]->()
1 Like
I didn't know that. Sounds like it'll be useful in the future. Thanks, Tard.