Reputation: 21652
UPDATE: I've changed the graphic and example queries to make the request more clear. The basic idea is the same, but now I'm showing that there really are more than just two relationships. The idea is I want TWO of them to match, not necessarily ALL of them.
Given the following Neo4j graph:
Is it possible to specify a relationship in a query that requires that TWO specific relationships be there for a match, but not necessarily all, without simply stating each full matching path separately? I want a logical AND
on the relationship types, just like we have a logical OR
using the |
character.
This is how you would use a logical OR with the |
character:
// OR on MEMBER_OF and GRANT_GROUP_COMP
MATCH (p:Person {name:'John'})-[r:MEMBER_OF|GRANT_GROUP_COMP]->(t:Team {name:'Team 1'})
RETURN p,r,t
What I'm looking for is something like this, an AND with a &
or simlar that REQUIRES that both relationships be present:
// AND type functionality in the relationship I'd like
MATCH (p:Person {name:'John'})-[r:MEMBER_OF&GRANT_GROUP_COMP]->(t:Team {name:'Team 1'})
RETURN p,r,t
Without having to resort to this - which works for me just fine:
// I'd like to avoid this
MATCH (p:Person {name:'John'})-[r:MEMBER_OF]->(t:Team {name:'Team 1'}),
(p)-[r2:GRANT_GROUP_COMP]->(t)
RETURN p,r,r2,t
Any insight would be appreciated, but based on responses so far, it simply doesn't exist.
Upvotes: 4
Views: 648
Reputation: 66999
This query will return a result if John
and Team 1
have MEMBER_OF
AND GRANT_GROUP_COMP
relationships between them.
(This is very similar to the second answer of @stdob--, but requires the size of types
to be exactly 2.)
MATCH (p:Person {name: 'John'})-[r:MEMBER_OF|GRANT_GROUP_COMP]->(t:Team {name: 'Team 1'})
WITH p, t, COLLECT(r) AS rels, COLLECT(DISTINCT type(r)) AS types
WHERE SIZE(types) = 2
RETURN p, t, rels;
Upvotes: 2
Reputation: 11216
You could add the second relationship type in a WHERE
clause. Something like this...
MATCH (p:Person {name:'John'})-[r:GRANT_GROUP_COMP]->(t:Team {name:'Team 1'})
WHERE (p)-[:MEMBER_OF]->(t)
RETURN *
Or you could make sure that the complete set is in the collection of relationship types. Something like this...
MATCH (p:Person {name:'John'})-[r]->(t:Team {name:'Team 1'})
with p,t,collect(type(r)) as r_types
where all(r in ['MEMBER_OF','GRANT_GROUP_COMP'] where r in r_types)
RETURN p, t, r_types
Upvotes: 1
Reputation: 29172
What about this?
MATCH (D:Person {name:'Donald'})-[r1:WORKS_AT]->
(o:Office {code:'279'})<-[r2:SUPPORTS]-(D)
RETURN *
Inspired version of Dave
MATCH (D:Person {name:'Donald'})-[r:WORKS_AT|SUPPORTS]->(o:Office {code:'279'})
WITH D, o, collect(r) as rels,
collect(distinct type(r)) as tmp WHERE size(tmp) >= 2
return D, o, rels
Update:
MATCH (D:Person {name:'Donald'})
- [r: MEMBER_OF
| GRANT_INDIRECT_ALERTS
| GRANT_INDIRECT_COMP
| GRANT_GROUP_ALERTS
| GRANT_GROUP_COMP
] ->
(o:Office {code:'279'})
WITH D, o, collect(r) as rels,
collect(distinct type(r)) as tmp WHERE size(tmp) >= 2 AND size(tmp) <= 5
return D, o, rels
Upvotes: 3