Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
01-16-2021 05:36 AM
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!
01-16-2021 07:22 AM
see Predicate functions - Neo4j 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;
01-16-2021 03:32 PM
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.
01-16-2021 05:41 PM
Yeah. My response may have over complicated
01-17-2021 04:13 AM
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
01-17-2021 04:15 AM
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.
01-17-2021 10:57 AM
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]->()
01-18-2021 12:25 PM
I didn't know that. Sounds like it'll be useful in the future. Thanks, Tard.
All the sessions of the conference are now available online