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
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.
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.
No need for a side effect...
g.V().transform{[it, it.in('likes').count()]}