Gremlin 从与单个顶点相关的边列表中获取最高值

Posted

技术标签:

【中文标题】Gremlin 从与单个顶点相关的边列表中获取最高值【英文标题】:Gremlin get highest value from list of edges related to a single vertice 【发布时间】:2021-12-28 11:25:03 【问题描述】:

我是 Tinkerpop 的 gremlin 初学者。我有这张图:


// -------- 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)

我想创建一个使用 userId g.V(id) 的查询,并获取它的所有朋友 outE("friend").inV(),以及他们唯一的最高评价边缘 outE("review").order().by("value", desc)

我已经创建了这个函数(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);

但这会返回一个朋友的所有评论。我只想要他们的最高评价。

提前致谢!

【问题讨论】:

我会尝试看看这个并感谢您提供示例图。这在测试答案时总是很有帮助的。但是,请注意,在添加边时,您不应假设顶点 ID 是什么,因为这会在数据库之间甚至使用相同的数据库之间有很大差异。 感谢您的建议!此查询特定于 Tinkerpop 服务器会话。我不知道如何保存数据。我创建了这个文本文件来在我启动服务器时重新初始化图形。 您可以使用g.io() 步骤保存数据。一般来说,当使用addV 这样的步骤创建图形时,最好使用as 标签。这是一个正在完成的示例***.com/questions/69959434/… 【参考方案1】:

使用 TinkerGraph,我将您的数据设置如下,

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)

然后,我稍微修改了您的查询,使用local 范围仅返回每个朋友的 1 条边,并按降序排序。我不确定您是否只是想要边缘或整个路径。如果您需要路径,请添加评论,我会更新答案。

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]       

【讨论】:

非常感谢您的回答。我看到您是与 gremlin 相关的查询的主要贡献者之一,对此我表示感谢。出于某种原因,这是在value:12 上方返回value: 4js gremlin> :> g.V(6).outE("friend").inV().hasLabel("user").local(__.outE("review").order().by("value", desc).limit(1).valueMap()) ==>upvotes=8, rated_at=Wed Nov 17 17:11:58 PKT 2021, downvotes=4, value=4 ==>upvotes=3, rated_at=Wed Nov 17 17:11:58 PKT 2021, downvotes=1, value=12 ==>upvotes=8, rated_at=Wed Nov 17 17:11:58 PKT 2021, downvotes=4, value=3.7 Nvm,最后只需要使用 order().bY()。感谢您的帮助! 另外,如果您可以解释或链接到有关 local() 的资源,那将对我有所帮助。 Tinkerpop 文档中的定义很难理解。 你见过kelvinlawrence.net/book/PracticalGremlin.html吗? 和相关链接kelvinlawrence.net/book/PracticalGremlin.pdf和github.com/krlawrence/graph。具体到本地看这里kelvinlawrence.net/book/PracticalGremlin.html#local

以上是关于Gremlin 从与单个顶点相关的边列表中获取最高值的主要内容,如果未能解决你的问题,请参考以下文章

Gremlin 中的决策树查询

如何在单个 gremlin 查询中将两个顶点详细信息和边属性详细信息合并在一起

如何使用 Gremlin 从我在 Titan 中关注的所有用户(边缘)获取帖子(顶点)

如何从顶点scala gremlin获取所有传入/传出边的所有顶点

Django:如何从与用户相关的子查询集中获取不同的父列表?

Gremlin删除所有顶点