0
votes

I want to retrieve all vertexes and for each one I want to count the number of 'Like' edges pointing at it.

How do I write this kind of query in Gremlin?

In SQL it could be something like....

SELECT *, (SELECT Count(*) FROM tbl_like l WHERE l.id = b.id) AS LikeCount
FROM tbl_blah b
3

3 Answers

1
votes

E.g. use sideEffect to put the counts in a map (m)

m=[:];g.V.sideEffect{m[it]=it.inE.has('label','like').count()}

An alternative which omits vertices with 0 likes:

m=[:];g.V.inE('like').groupCount(m){it.inV.next()}

EDIT

Finally the smart solution:

 m=[:];g.V.groupCount(m){it}{it.a.inE('like').count()}

The first closure of groupCount determines the key to update in the map and the second closure the value to the key. Seems like it.a in the second closure gives the current input value to groupCount (here a vertex) and it.b the previous value in the map for the input object. Haven't really found a documentation that explains this, maybe one of the TinkerPop guys can elaborate on the exact usage of the groupCount closures.

1
votes

I would consider:

m = g.E.has('label','like').groupBy{it.inV.next()}{1}{it.sum()}.cap.next()

Iterate all edges and filter by label, group on the inV of each "like" edge and add a 1 to that Map of results. That much takes you to the second to last closure of the groupBy. At that point you will have a Map like:

[v1:[1,1,1]
 v2:[1,1]]

which basically is a vertex with a 1 representing each "like" edge. Going back to the Gremlin above, the final closure to groupBy is a reduce operation that occurs on the values in the Map. In this case, we use the Groovy sum function (though I suppose size would work here too - but sum seems easier for readability) to add up the number of edges. Finally, we use cap to extract the Map side-effect from the pipeline and next it out into a var.

I suppose the downside here is that it doesn't yield a result for vertices with no "like" edges. If you need that, then the solution provided by @Faber is a better way to go. You might even pick and choose a bit from both solutions to ultimately get at what you are looking for.

0
votes

No need for a side effect...

g.V().transform{[it, it.in('likes').count()]}