Reputation: 6137
With variable length relationships (see here in the neo4j manual), it is possible to have a variable number of relationships with a certain label between two nodes.
# Cypher
match (g1:Group)-[:sub_group*]->(g2:Group) return g1, g2
I'm looking for the same thing with nodes, i.e. a way to query for two nodes with a variable number of nodes in between, but with a label condition on the nodes rather than the relationships:
# Looking for something like this in Cypher:
match (g1:Group)-->(:Group*)-->(g2:Group) return g1, g2
I would use this mechanism, for example, to find all (direct or indirect) members of a group within a group structure.
# Looking for somthing like this in Cypher:
match (group:Group)-->(:Group*)-->(member:User) return member
Take, for example, this structure:
group1:Group
|-------> group2:Group -------> user1:User
|-------> group3:Group
|--------> page1:Page -----> group4:Group -----> user2:User
In this example, user1
is a member of group1
and group2
, but user2
is only member of group4
, not member of the other groups, because a non-Group
labeled node is in between.
A more abstract pattern would be a kind of repeat operator |...|*
in Cypher:
# Looking for repeat operator in Cypher:
match (g1:Group)|-[:is_subgroup_of]->(:Group)|*-[:is_member_of]->(member:User)
return member
Does anyone know of such a repeat operator? Thanks!
Upvotes: 2
Views: 1875
Reputation: 1949
How about this:
MATCH (:Group {id:1})<-[:IS_SUBGROUP_OF|:IS_MEMBER_OF*]-(u:User)
RETURN DISTINCT u
This will:
I know this relies on relationships types rather than node labels, but IMHO this is a more graphy approach.
Let me know if this would work or not.
Upvotes: 1
Reputation: 6137
One solution I've found, is to use a condition on the nodes using where
, but I hope, there is a better (and shorter) soluation out there!
# Cypher
match path = (member:User)<-[*]-(g:Group{id:1})
where all(node in tail(nodes(path)) where ('Group' in labels(node)))
return member
In the above query, all(node in tail(nodes(path)) where ('Group' in labels(node)))
is one single where condition, which consists of the following key parts:
all
: ALL(x in coll where pred)
: TRUE if pred
is TRUE for all values in
coll
nodes(path)
: NODES(path)
: Returns the nodes in path
tail()
: TAIL(coll)
: coll
except first element–––I'm using this, because the first node is a User
, not a Group
.Upvotes: 3