graphtitangremlingraph-traversalproperty-graph

Gremlin: how do I merge selected attributes of two objects encountered on a traversal path


Let us suppose I have apples which come from trees on various farms. So trees bear apples, and farms have trees. I want a list of apples which also contain a reference to the farm they come from.

g = new TinkerGraph();

// apples
a1 = g.addVertex("a1");
a1.setProperty("type", "apple");

a2 = g.addVertex("a2");
a2.setProperty("type", "apple");

a3 = g.addVertex("a3");
a3.setProperty("type", "apple");


// trees
t1 = g.addVertex("t1");
t1.setProperty("type", "tree");

t2 = g.addVertex("t2");
t2.setProperty("type", "tree");


// farms
f1 = g.addVertex("f1");
f1.setProperty("type", "farm");
f1.setProperty("uid", "f1");

f2 = g.addVertex("f2");
f2.setProperty("type", "farm");
f2.setProperty("uid", "f2");

g.addEdge(t1, a1, "bears");
g.addEdge(t1, a2, "bears");
g.addEdge(t2, a3, "bears");

g.addEdge(f1, t1, "has");
g.addEdge(f2, t2, "has");

I want to traverse and the graph to report each apple, and also include the farm id in it. I tried something like this:

g.V.has("type", "apple").copySplit(_().in("bears").in("has").map("uid"),
                                  _().map()).fairMerge

The output I get is:

==>{uid=f1}
==>{type=apple}
==>{uid=f1}
==>{type=apple}
==>{uid=f2}
==>{type=apple}

What I want is:

==>{uid=f1, type=apple}
==>{uid=f1, type=apple}
==>{uid=f2, type=apple}

Solution

  • Assuming TinkerPop 2.x, you might do this with a transform:

    gremlin> g.V.has("type", "apple").transform{
    gremlin>   m = [:] 
    gremlin>   m<<it.in("bears").in("has").map("uid").next(); 
    gremlin>   m<<it.map() }
    ==>{uid=f1, type=apple}
    ==>{uid=f1, type=apple}
    ==>{uid=f2, type=apple}
    

    The << syntax just behaves like a putAll() on the Map of "m".

    In TinkerPop 3.x (which you should be using unless you have very good reason), a rough approximation of this would be:

    graph = TinkerGraph.open()
    a1 = graph.addVertex(label, 'apple')
    a2 = graph.addVertex(label, 'apple')
    a3 = graph.addVertex(label, 'apple')
    t1 = graph.addVertex(label, 'tree')
    t2 = graph.addVertex(label, 'tree')
    f1 = graph.addVertex(label, 'farm', 'uid', 'f1')
    f2 = graph.addVertex(label, 'farm', 'uid', 'f2')
    t1.addEdge('bears',a1)
    t1.addEdge('bears',a2)
    t2.addEdge('bears',a3)
    f1.addEdge('has',t1)
    f2.addEdge('has',t2)
    

    with:

    gremlin> g = graph.traversal()
    ==>graphtraversalsource[tinkergraph[vertices:7 edges:5], standard]
    gremlin> g.V().hasLabel("apple").as('type').in('bears').in('has').as('uid').select('type','uid').by(label()).by('uid')
    ==>[type:apple, uid:f1]
    ==>[type:apple, uid:f1]
    ==>[type:apple, uid:f2]