Reputation: 2035
if i have a graph that looks like:
N3->member_of->N1
N2->knows->N1
N3->likes->N2
N4->member_of->N1
N5->likes->N2
Is there a way to do a single query that will do the following:
(preferably in gremlin)
EDIT: Clarification: I can go through up to a 2nd degree connection, as long as the first degree relationship is "member_of".
Upvotes: 2
Views: 992
Reputation: 10904
Pretty old question, but since nobody came up with a Gremlin solution, here it is:
I took Bobbys initialization script:
g = new TinkerGraph()
(1..5).each { g.addVertex(it) }
g.addEdge(g.v(3), g.v(1), "member_of")
g.addEdge(g.v(2), g.v(1), "knows")
g.addEdge(g.v(3), g.v(2), "likes")
g.addEdge(g.v(5), g.v(2), "likes")
g.addEdge(g.v(4), g.v(1), "member_of")
And here's your Gremlin query:
gremlin> g.v(3).copySplit(_().out('likes'), _().out('member_of').loop('start'){true}{true}.in('knows')).exhaustMerge().dedup()
==>v[2]
gremlin> g.v(4).copySplit(_().out('likes'), _().out('member_of').loop('start'){true}{true}.in('knows')).exhaustMerge().dedup()
==>v[2]
gremlin> g.v(5).copySplit(_().out('likes'), _().out('member_of').loop('start'){true}{true}.in('knows')).exhaustMerge().dedup()
==>v[2]
Cheers, Daniel
Upvotes: 3
Reputation: 14849
Is the idea that you want to return all incoming and outgoing relationships of a node (person?), and all related nodes of any group of which a person is a member? So "groups" commute their relationships on "members"?
If so, and assuming recursive groups aren't allowed, I've come up with an alternative graph that might illustrate your use case (as I understand it) more clearly -> http://console.neo4j.org/?id=wyr207
If you run
start n=node(5) match n-[?:knows|likes]-related, n-[?:member_of]->group-[:knows|likes]-other_related return related, other_related
on the graph, related
would return all directly related nodes, and other_related
all other nodes returned from a group, if the node is a member of a group. Combining those is beyond my Cypher ability, but they will be de-duped AFAIK (no nodes in related
will be included in other_related
).
Try the query in the console link with a few different node ids (N5 has a node id of 1) and see if that's what you were thinking. It would be simple to add relationship direction, etc.
Translating this to Gremlin is a tad bit tedious (pattern matching in Cypher is more natural), but LMK if this is in the right direction and I'll do it.
Upvotes: 0
Reputation: 1504
First create your graph in a Gremlin Groovy shell using a TinkerGraph:
g = new TinkerGraph()
(1..5).each { g.addVertex(it) }
g.addEdge(g.v(3), g.v(1), "member_of")
g.addEdge(g.v(2), g.v(1), "knows")
g.addEdge(g.v(3), g.v(2), "likes")
g.addEdge(g.v(5), g.v(2), "likes")
g.addEdge(g.v(4), g.v(1), "member_of")
It sounds like you want a query that starts at vertices 3, 4, or 5 and returns vertex 2. The queries below use the algorithm:
gremlin> g.v(3).both.loop(1) {it.loops < 3}{it.object.id == "2"}.next()
==>v[2]
gremlin> g.v(4).both.loop(1) {it.loops < 3}{it.object.id == "2"}.next()
==>v[2]
gremlin> g.v(5).both.loop(1) {it.loops < 3}{it.object.id == "2"}.next()
==>v[2]
You might also find the Gremlin documentation on the path pattern to be useful.
Upvotes: 0
Reputation: 6331
not sure your setup is correct, tried to do it here: http://tinyurl.com/d2mjkj2 - the setup correct?
If the first relationship type needs to be member_of
then N5 should not return N2. Otherwise, you can do something like
start s=node(3,4,5) match s-[r1:member_of]->()<-[r2*0..1]-end return s,end
to return patterns that start with a member_of
relationship, and then have 0 or 1 relationships of any type. Tighten this up if you want, see http://docs.neo4j.org/chunked/snapshot/query-match.html#match-variable-length-relationships for details.
Upvotes: 0
Reputation: 5918
this is how it would look in cypher:
1: start n=node(3) match n-[:LIKES]->m return m;
2: start n=node(4) match n-[:MEMBER_OF]-m-[]-k return k; (will return n2,n3. if you want n2 only match n-[:MEMBER_OF]-m-[:KNOWS]-k )
3: the same as 1)
Upvotes: 0