Search code examples
gremlintinkerpoptinkerpop3janusgraphgremlin-server

Joining vertices with type indirection


I want to do a join between two vertex types using gremlin

select * from type1 inner join type2 in type2.id = type1.type2_id

The following works when using type1 and type2 as vertex labels:

g.V()
  .hasLabel("type2").as("t2")
  .inE("hasJoin")
  .hasLabel("type1").as("t1")
  .select("t1", "t2")

However, my graph does not use the vertex label to represent the type, but uses another vertex connected via the "hasType" edge instead.

g.V()//
    .addV("instance1").as("instance1")//
    .addV("instance2").as("instance2")//
    .addV("type1").as("type1")//
    .addV("type2").as("type2")//
    .addE("hasType").from("instance1").to("type1")//
    .addE("hasType").from("instance2").to("type2")//
    .addE("hasJoin").from("instance1").to("instance2")//
    .iterate();

I would need to do something like replacing

hasLabel("type2").as("t2")

with

hasLabel("type2").inE("hasType").outV().as("t2"):

which would result in

g.V()
  .hasLabel("type2").inE("hasType").outV().as("t2")
  .inE("hasJoin")
  .hasLabel("type1").inE("hasType").outV().as("t1")
  .select("t1", "t2")

This works for "t2", but not for "t1", as .inE("hasJoin").hasLabel("type1") is just wrong. What function do I need to use to join "t1" and "t2"?


Solution

  • All you need is a filter that checks the adjacent type vertex. Here's your sample graph (your script doesn't quite work):

    gremlin> g = TinkerGraph.open().traversal()
    ==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
    gremlin> g.addV("instance1").property("name","instance1").as("instance1").
    ......1>   addV("instance2").property("name","instance2").as("instance2").
    ......2>   addV("type1").as("type1").
    ......3>   addV("type2").as("type2").
    ......4>   addE("hasType").from("instance1").to("type1").
    ......5>   addE("hasType").from("instance2").to("type2").
    ......6>   addE("hasJoin").from("instance1").to("instance2").
    ......7>   iterate()
    

    And the query you're looking for should be something like this:

    gremlin> g.V().hasLabel("type2").in("hasType").as("t2").
               both("hasJoin").
               filter(out("hasType").hasLabel("type1")).as("t1").
               select("t1", "t2").
                 by("name")
    ==>[t1:instance1,t2:instance2]