Search code examples
javascriptgremlingraph-databasestinkerpop

Gremlin get highest value from list of edges related to a single vertice


I am a beginner in gremlin with Tinkerpop. I've this graph:


// -------- VERTICES ------------
// USERS:

 :> g.addV("user").property("name", "test1").property("location", "karachi")

 :> g.addV("user").property("name", "test2").property("location", "lahore")

 :> g.addV("user").property("name", "test3").property("location", "islamabad")

 :> g.addV("user").property("name", "test4").property("location", "karachi")


// RESTAURANTS:

 :> g.addV("restaurant").property("name", "restaurant1").property("location", "karachi")


 :> g.addV("restaurant").property("name", "restaurant2").property("location", "lahore")

 :> g.addV("restaurant").property("name", "restaurant3").property("location", "islamabad")

 :> g.addV("restaurant").property("name", "restaurant4").property("location", "faisalabad")


// CUISINES:

 :> g.addV("cuisine").property("name", "cuisine1")

 :> g.addV("cuisine").property("name", "cuisine2")

 :> g.addV("cuisine").property("name", "cuisine3")

 :> g.addV("cuisine").property("name", "cuisine4")

 :> g.addV("cuisine").property("name", "cuisine5")


// -------- EDGES ------------

FRIENDS:

 :> g.addE("friend").from(__.V(0)).to(__.V(6)).property("became_friends_at", new Date())

 :> g.addE("friend").from(__.V(6)).to(__.V(0)).property("became_friends_at", new Date())

 :> g.addE("friend").from(__.V(6)).to(__.V(9)).property("became_friends_at", new Date())

 :> g.addE("friend").from(__.V(9)).to(__.V(6)).property("became_friends_at", new Date())

 :> g.addE("friend").from(__.V(6)).to(__.V(3)).property("became_friends_at", new Date())

 :> g.addE("friend").from(__.V(3)).to(__.V(6)).property("became_friends_at", new Date())


// REVIEWS:

 :> g.addE("review").from(__.V(3)).to(__.V(12)).property("value", 3.7).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4)

 :> g.addE("review").from(__.V(0)).to(__.V(12)).property("value", 4).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4)

 :> g.addE("review").from(__.V(0)).to(__.V(21)).property("value", 2.5).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4)

 :> g.addE("review").from(__.V(6)).to(__.V(15)).property("value", 3.9).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4)

 :> g.addE("review").from(__.V(9)).to(__.V(18)).property("value", 5).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4)



// SERVED CUISINES:

 :> g.addE("serves").from(__.V(18)).to(__.V(24))

 :> g.addE("serves").from(__.V(18)).to(__.V(26))

 :> g.addE("serves").from(__.V(18)).to(__.V(32))

 :> g.addE("serves").from(__.V(15)).to(__.V(32))

 :> g.addE("serves").from(__.V(15)).to(__.V(24))

 :> g.addE("serves").from(__.V(21)).to(__.V(30))

 :> g.addE("serves").from(__.V(12)).to(__.V(28))

 :> g.addE("serves").from(__.V(12)).to(__.V(26))

 :> g.addE("serves").from(__.V(12)).to(__.V(30))



 :> g.addV("restaurant").property("name", "restaurant5").property("location", "karachi")

 :> g.addV("restaurant").property("name", "restaurant6").property("location", "karachi")

 :> g.addV("restaurant").property("name", "restaurant7").property("location", "karachi")

 :> g.addE("serves").to(__.V(26)).from(__.V(54))

 :> g.addE("serves").to(__.V(26)).from(__.V(60))



 :> g.addE("review").from(__.V(6)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 1).property("value",4).property("upvotes",4)
 :> g.addE("review").from(__.V(0)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 3).property("value",2).property("upvotes",4.7)
 :> g.addE("review").from(__.V(9)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 1).property("value",12).property("upvotes",3)
 :> g.addE("review").from(__.V(3)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 9).property("value",3).property("upvotes",2)

 :> g.addE("review").from(__.V(6)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 3).property("value",5).property("upvotes",4)
 :> g.addE("review").from(__.V(0)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 2).property("value",3).property("upvotes",5)
 :> g.addE("review").from(__.V(9)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 5).property("value",5).property("upvotes",1)
 :> g.addE("review").from(__.V(3)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 1).property("value",2).property("upvotes",5)

I want to create a query that takes the userId g.V(id), and get all of its friends outE("friend").inV(), and their only highest review edge outE("review").order().by("value", desc)

I've created this function (JS):

async function init() {
  const query = g
    .V()
    .hasId(6)
    .outE("friend")
    .inV()
    .hasLabel("user")
    .outE("review")
    .order()
    .by("value", queryOrder);

  const dataRaw = await query.toList();
  await dc.close();
  const data = JSON.stringify(normalizeData(dataRaw as any), null, 1);
  console.log(data);
}

But this returns all the reviews of a single friend. I want only the highest review of them.

Thanks in advance!


Solution

  • Using TinkerGraph, I setup your data as follows,

    conf = new BaseConfiguration()
    conf.setProperty("gremlin.tinkergraph.vertexIdManager","LONG")
    conf.setProperty("gremlin.tinkergraph.edgeIdManager","LONG")
    conf.setProperty("gremlin.tinkergraph.vertexPropertyIdManager","LONG")
    graph = TinkerGraph.open(conf)
    g=graph.traversal()
    
    g.addV("user").property("name", "test1").property("location", "karachi").
       addV("user").property("name", "test2").property("location", "lahore").
       addV("user").property("name", "test3").property("location", "islamabad").
       addV("user").property("name", "test4").property("location", "karachi").
       addV("restaurant").property("name", "restaurant1").property("location", "karachi").
       addV("restaurant").property("name", "restaurant2").property("location", "lahore").
       addV("restaurant").property("name", "restaurant3").property("location", "islamabad").
       addV("restaurant").property("name", "restaurant4").property("location", "faisalabad").
       addV("cuisine").property("name", "cuisine1").
       addV("cuisine").property("name", "cuisine2").
       addV("cuisine").property("name", "cuisine3").
       addV("cuisine").property("name", "cuisine4").
       addV("cuisine").property("name", "cuisine5").
       addE("friend").from(__.V(0)).to(__.V(6)).property("became_friends_at", new Date()).
       addE("friend").from(__.V(6)).to(__.V(0)).property("became_friends_at", new Date()).
       addE("friend").from(__.V(6)).to(__.V(9)).property("became_friends_at", new Date()).
       addE("friend").from(__.V(9)).to(__.V(6)).property("became_friends_at", new Date()).
       addE("friend").from(__.V(6)).to(__.V(3)).property("became_friends_at", new Date()).
       addE("friend").from(__.V(3)).to(__.V(6)).property("became_friends_at", new Date()).
       addE("review").from(__.V(3)).to(__.V(12)).property("value", 3.7).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4).
       addE("review").from(__.V(0)).to(__.V(12)).property("value", 4).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4).
       addE("review").from(__.V(0)).to(__.V(21)).property("value", 2.5).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4).
       addE("review").from(__.V(6)).to(__.V(15)).property("value", 3.9).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4).
       addE("review").from(__.V(9)).to(__.V(18)).property("value", 5).property("rated_at", new Date()).property("upvotes", 8).property("downvotes", 4).
       addE("serves").from(__.V(18)).to(__.V(24)).
       addE("serves").from(__.V(18)).to(__.V(26)).
       addE("serves").from(__.V(18)).to(__.V(32)).
       addE("serves").from(__.V(15)).to(__.V(32)).
       addE("serves").from(__.V(15)).to(__.V(24)).
       addE("serves").from(__.V(21)).to(__.V(30)).
       addE("serves").from(__.V(12)).to(__.V(28)).
       addE("serves").from(__.V(12)).to(__.V(26)).
       addE("serves").from(__.V(12)).to(__.V(30)).
       addV("restaurant").property("name", "restaurant5").property("location", "karachi").
       addV("restaurant").property("name", "restaurant6").property("location", "karachi").
       addV("restaurant").property("name", "restaurant7").property("location", "karachi").
       addE("serves").to(__.V(26)).from(__.V(54)).
       addE("serves").to(__.V(26)).from(__.V(60)).
       addE("review").from(__.V(6)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 1).property("value",4).property("upvotes",4).
       addE("review").from(__.V(0)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 3).property("value",2).property("upvotes",4.7).
       addE("review").from(__.V(9)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 1).property("value",12).property("upvotes",3).
       addE("review").from(__.V(3)).to(__.V(54)).property("rated_at", new Date()).property("downvotes", 9).property("value",3).property("upvotes",2).
       addE("review").from(__.V(6)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 3).property("value",5).property("upvotes",4).
       addE("review").from(__.V(0)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 2).property("value",3).property("upvotes",5).
       addE("review").from(__.V(9)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 5).property("value",5).property("upvotes",1).
       addE("review").from(__.V(3)).to(__.V(60)).property("rated_at", new Date()).property("downvotes", 1).property("value",2).property("upvotes",5)
    

    I then slightly modified your query to only return 1 edge per friend using local scope, having sorted by descending value. I was not sure from the question if you just wanted the edge back or the whole path. If you need the path please add a comment and I will update the answer.

    gremlin> g.V(6).
    ......1>   outE("friend").
    ......2>   inV().
    ......3>   hasLabel("user").
    ......4>   local(
    ......5>     outE("review").
    ......6>     order().
    ......7>       by("value", desc).
    ......8>     limit(1)) 
    ==>e[41][0-review->12]
    ==>e[67][9-review->54]
    ==>e[40][3-review->12]