简体   繁体   中英

TinkerPop/Graph: Traverse edge and then group by resulting vertex and traversed edge

Given the example below:

marko = graph.addVertex(label, "person", id, 1, "name", "marko", "age", 29);
vadas = graph.addVertex(label, "person", id, 2, "name", "vadas", "age", 27);
josh = graph.addVertex(label, "person", id, 4, "name", "josh", "age", 32);
peter = graph.addVertex(label, "person", id, 5, "name", "peter", "age", 35);
lop = graph.addVertex(label, "software", id, 6, "name", "lop", "lang", "java");
ripple = graph.addVertex(label, "software", id, 7, "name", "ripple", "lang", "java");
tripple = graph.addVertex(label, "software", id, 8, "name", "tripple", "lang", "java");

marko.addEdge("created", lop, id, 9, "weight", 0.4f);
josh.addEdge("created", ripple, id, 10, "weight", 1.0f);
josh.addEdge("created", lop, id, 11, "weight", 0.4f);
peter.addEdge("created", lop, id, 12, "weight", 0.2f);
peter.addEdge("created", tripple, id, 13, "weight", 0.2f);
vadas.addEdge("created", tripple, id, 14, "weight", 0.2f);

I want to start with software vertices lop and ripple, find all persons which created lop and ripple and which are older than 32. Then I want to group by person and the created weigth on lop and ripple.

So I created something which gives me a result but it looks rather comlicated:

g.V(6,7).as('soft').
in('created').has('age',gte(32)).
group()
by()
by(
  outE().where(
    inV().where(eq('soft'))
  ).fold())
.unfold()

==>v[4]=[e[11][4-created->6], e[10][4-created->7]]
==>v[5]=[e[12][5-created->6]]

Also, I want the end result to have a structure similar to this (sorry if I did not get the syntax right):

==>v[4,person,josh,32]=[lop=0.4, ripple=1.0]
==>v[5,person,peter,35]=[lop=0.2]

So I need the complete person vertex with all its contents and a list of all edges which lead to lop and ripple.

The json representation would look like:

[{
        "id": 4,
        "label": "person",
        "name": "josh",
        "age": "32",
        "software": [{
                "name": "lop",
                "weigth": 0.4
            },
            {
                "name": "ripple",
                "weigth": 1.0
            }
        ]
    },
    {
        "id": 5,
        "label": "person",
        "name": "peter",
        "age": "35",
        "software": [{
            "name": "lop",
            "weigth": 0.2
        }]
    }
]

Interesting question. I think the more complex part is in the transformation to the form you want rather than the actual data retrieval. Your approach to retrieval is fine, though I wrote it this way:

gremlin> g.V(6,7).
......1>   inE('created').as('e').outV().has('age',gte(32)).as('p').
......2>   group().
......3>    by(select('p')).
......4>    by(select('e').fold()).
......5>   unfold()
==>v[4]=[e[11][4-created->6], e[10][4-created->7]]
==>v[5]=[e[12][5-created->6]]

I think that's a little easier to read, because it's clear that you're selecting these elements from the traversal path and then operating on them rather than using elements from the traversal path for filtering. But, it's debatable whether or not it's better. It wouldn't surprise me to see another way to get this initial output, but that's what first came to mind for me.

The real question is how to translate that output to the expected form you requested and for that I took this approach:

gremlin> g.V(6,7).
......1>   inE('created').as('e').outV().has('age',gte(32)).as('p').
......2>   group().
......3>    by(select('p')).
......4>    by(select('e').fold()).
......5>   unfold().
......6>   project('id','label','name','age','software').
......7>     by(select(keys).id()).
......8>     by(select(keys).label()).
......9>     by(select(keys).values('name')).
.....10>     by(select(keys).values('age')).
.....11>     by(select(values).
.....12>        unfold().
.....13>        project('name','weight'). 
.....14>          by(inV().values('name')).
.....15>          by('weight').
.....16>        fold())
==>[id:4,label:person,name:josh,age:32,software:[[name:lop,weight:0.4],[name:ripple,weight:1.0]]]
==>[id:5,label:person,name:peter,age:35,software:[[name:lop,weight:0.2]]]

I simply used project() to convert the unfolded Map of "person" vertex and edge list to the desired structure. Note the final by() of that project() in that it requires its own embedded project() to deal with the unfolded list of edges in the values of the original Map . The key there is to fold() back those transformed edges into a List so that they are all accounted for (otherwise by() would only deal with the first).

You can read more about collection manipulation in Gremlin Recipes .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM