I have started working on gremlin with apache tinkerpop , I am trying to get the vertices based on the similar property from another vertex, using the single query. A kind of simple dynamic where clause.
Here is my use case, there are 2 types of vertex labels "website" and "device"
A "device" is visiting a "website", one more more "device" can visit website. A website can be classified in categories, like music, news, automobile etc. I want to query similar websites based on one website name as a input.
Here is my tinker pop console in which I am creating. vertex and relationships.
g = traversal().withEmbedded(TinkerGraph.open());
// Create websites
w1 = g.addV('website').property('name','W-ABC').property('category','A').next()
w2 = g.addV('website').property('name','W-DEF').property('category','A').next()
w3 = g.addV('website').property('name','W-GHI').property('category','B').next()
w4 = g.addV('website').property('name','W-JKL').property('category','A').next()
// Create devices
d1 = g.addV('device').property('name','D-123').next()
d2 = g.addV('device').property('name','D-456').next()
d3 = g.addV('device').property('name','D-789').next()
// Create edges ( Device visiting websites )
g.V(d1).addE('visits').to(w1).iterate()
g.V(d2).addE('visits').to(w2).iterate()
g.V(d3).addE('visits').to(w3).iterate()
g.V(d3).addE('visits').to(w4).iterate()
Well i am trying to get websites similar to "W-ABC" based on the category. the input for me will be "W-ABC" and will be expecting a vertex "W-DEF" and "W-JKL" since they belong to same category "A"
This is the query i have written along with my assumption.
g.V() // Start with the gremlin with all vertices.
.hasLabel('website') // Narrow down to website vertices.
.has('name', 'W-ABC') // Further narrow down to vertex which has name "W-ABC" .
.as('k') // Save this W-ABC Vertex as "k"
.V() // Again Start with the gremlin with all vertices.
.hasLabel('website') // Narrow down to website vertices.
.has("category",select('k').values("category")) // Now select the website vertices which has a category same as "k"'s vertex category.
gremlin> g.V().hasLabel('website').has('name', 'W-ABC').as('k').V().hasLabel('website').has("category",select('k').values("category")).values('name')
==>W-ABC
==>W-DEF
==>W-GHI
==>W-JKL
I have also tried with limit(1) for AsStep so that only one vertex is in the memory still the same result.
gremlin> g.V().hasLabel('website').has('name', 'W-ABC').limit(1).as('k').V().hasLabel('website').has("category",select('k').values("category")).values('name')
==>W-ABC
==>W-DEF
==>W-GHI
==>W-JKL
Even on the 2nd query the same results, i am getting all the website vertices.
Appreciate if anyone could help me one this.
Your query is very close. While it seems like putting a select
inside has
should work the way you tried it, today it does not. It's something that can hopefully be improved in a future TinkerPop release.
In the meantime, there is a where()..by()
pattern that works. Using your sample graph:
gremlin> g.V().
......1> hasLabel('website').
......2> has('name', 'W-ABC').
......3> as('k').
......4> V().
......5> hasLabel('website').
......6> where(eq('k')).
......7> by('category').
......8> valueMap('name','category')
==>[name:[W-ABC],category:[A]]
==>[name:[W-DEF],category:[A]]
==>[name:[W-JKL],category:[A]]
If you want to avoid having W-ABC in the results, you can do that as follows:
gremlin> g.V().
......1> hasLabel('website').
......2> has('name', 'W-ABC').
......3> as('k').
......4> V().
......5> hasLabel('website').
......6> where(neq('k')).
......7> where(eq('k')).
......8> by('category').
......9> valueMap('name','category')
==>[name:[W-DEF],category:[A]]
==>[name:[W-JKL],category:[A]]