0

Consider the following graph:

enter image description here

I want to find all the pairs of people who have a FOLLOWS relationship between them and have reviewed the same movie. In Cypher, I would do the following:

MATCH (p:Person) -[:REVIEWED]-> (m:Movie)
MATCH (p) -[:FOLLOWS]-> (p2:Person)
MATCH (p2) -[:REVIEWED]-> (m)
RETURN p, p2, m

What I have so far in Gremlin:

g.V().hasLabel('person').as('p')
 .out('REVIEWED').as('m')
 .in('REVIEWED').as('p2')
 .where(in('FOLLOWS').is(select('p')))   // this doesn't work
 .select('p', 'm', 'p2')

But this doesn't work. How can I get achieve this in Gremlin?

jacob
  • 160
  • 8

1 Answers1

2

You are actually very close. Try this

g.V().hasLabel('person').as('p')
 .out('REVIEWED').as('m')
 .in('REVIEWED').as('p2')
 .where(in('FOLLOWS').as('p'))  
 .select('p', 'm', 'p2')

We can test the query using this simple graph

g.addV('Person').property('name','P1').as('p1').
  addV('Person').property('name','P2').as('p2').
  addV('Person').property('name','P3').as('p3').
  addV('Movie').property('name','Shrek').as('m1').
  addE('REVIEWED').from('p1').to('m1').
  addE('REVIEWED').from('p2').to('m1').
  addE('REVIEWED').from('p3').to('m1').
  addE('FOLLOWS').from('p1').to('p3') 

and we can see that it works using the Gremlin Console

gremlin> g.V().hasLabel('Person').as('p').
......1>       out('REVIEWED').as('m').
......2>       in('REVIEWED').as('p2').
......3>       where(__.in('FOLLOWS').as('p')).
......4>       select('p', 'm', 'p2').by('name')

==>[p:P1,m:Shrek,p2:P3] 
Kelvin Lawrence
  • 14,674
  • 2
  • 16
  • 38
  • Thanks, this works. I thought underscores were used to avoid gremlin functionality conflicting with language built-ins. If that's the case, can you tell me why underscores are needed when using the console? – jacob Jan 04 '22 at 17:20
  • 1
    The Gremlin Console sits on top of the Groovy Console - it's to avoid reserved word conflicts with Groovy (as Groovy will try to parse what is entered) – Kelvin Lawrence Jan 04 '22 at 17:22
  • @KelvinLawrence I tried this myself and it works (thank you!) . Does this also imply that the "as" step will never overwrite a previous step? For instance, once you use `.as("key")` a future step that tries to set `.as("key")` to a different vertex won't overwrite which vertex that "key" refers to? It's a bit distressing to me because I don't see anything in the documentation that explains how it works. – Adam Aug 11 '22 at 19:35
  • I'm not sure how well this is going to format as a comment, but in reality it will be creating a list known as `a`. For example `gremlin> g.addV('a').as('a').addV('b').as('a').select(all,'a') ==>[v[61286],v[61287]] ` I do cover it a bit here https://kelvinlawrence.net/book/PracticalGremlin.html#multias – Kelvin Lawrence Aug 11 '22 at 20:39
  • @KelvinLawrence I'm sorry to ask again. I'm still not sure I get how `where(in('FOLLOWS').as('p')` works. It looks like that where clause would pass if there we any 'FOLLOWS' edge incoming to the vertex. Does the `.as('p')` have something built in to not return in a where clause if 'p' isn't equal to its previous value? This is a question that I asked today that is similar, and was the issue I was trying to solve when I found this. https://stackoverflow.com/questions/73325404/gremlin-continue-traversal-only-if-2-vertices-are-not-the-same/73325811#73325811 – Adam Aug 11 '22 at 21:14
  • 1
    Ah OK - that is a special case of `as`. Read that `as` as `is the thing named as p`. It's similar to the way `as` gets overloaded in the `match` step. This allows you to pretty much write a declarative `match` like query just using a `where` step. – Kelvin Lawrence Aug 11 '22 at 22:54