Search code examples
graphgraph-databasesgremlintinkerpop3

Count incoming and outgoing edges from a given vertex to each neighbour in a multidigraph


I am trying to find a query that would allow me to get a sort of group count of incoming and outgoing vertices of a vertex in a multidigraph.

enter image description here

Taking the graph above for V[0], we should obtain :

[V[0],V[1],incoming:2,outgoing:0]

[V[0],V[2],incoming:1,outgoing:0]

[V[0],V[3],incoming:0,outgoing:1]


Solution

  • When asking questions about Gremlin, a picture and graph description are nice, but a Gremlin script creating some sample data is even better:

    g = TinkerGraph.open().traversal()
    g.addV('node').property(T.id,0).as('0').
      addV('node').property(T.id,1).as('1').
      addV('node').property(T.id,2).as('2').
      addV('node').property(T.id,3).as('3').
      addE('link').from('1').to('0').
      addE('link').from('1').to('0').
      addE('link').from('0').to('3').
      addE('link').from('2').to('0').iterate()
    

    Here's one way to do this:

    gremlin> g.V(0).bothE().
    ......1>   group().
    ......2>     by(union(inV(),outV()).fold()).
    ......3>     by(fold().
    ......4>        project('incoming','outgoing').
    ......5>          by(unfold().inV().hasId(0).count()).
    ......6>          by(unfold().outV().hasId(0).count()))
    ==>[[v[0],v[1]]:[incoming:2,outgoing:0],[v[0],v[2]]:[incoming:1,outgoing:0],[v[3],v[0]]:[incoming:0,outgoing:1]]
    

    Basically, we group() each edge by its associated in/out vertices (line 2 - i.e. a List of in/out formed by union().fold()) and then reduce the edges that are gathered per vertex pair (starting at line 3). The reduce operation simply creates a list with fold() then uses project() to transform that List to a Map with "incoming" and "outgoing" keys - the values for those keys are defined in the following respective by() modulators (i.e. unfold the list of edges, filter for vertex "0" appropriately and count()).