Search code examples
graph-theorygremlintinkerpoptinkerpop3gremlin-server

Germlin : Query vertices based on other vertex properties


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.


Solution

  • 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]]