【问题标题】:Tinkerpop/gremlin merge vertices (and edges)Tinkerpop/gremlin 合并顶点(和边)
【发布时间】:2017-09-22 11:30:03
【问题描述】:

是否有一种简单的方法可以替换或合并顶点并保留/合并现有边?或者只是手动从顶点复制所有属性并重新创建现有边和所有(元)属性,然后删除多余的顶点?

【问题讨论】:

  • 您能详细说明一下您的用例吗?你说的是进口吗?如果是这样,你如何导入顶点?您使用的是哪个图形数据库?
  • 我的用例是一个包含不同来源数据的知识图谱。该数据可以描述相同实体的不同方面。不同的来源并不总是具有这些实体的共同标识符。当有足够的数据时,我可以识别哪些顶点是关于同一个实体的,所以我想合并这些顶点(包括它们的顶点)。我使用的数据库应该无关紧要,但我使用的是 JanusGraph(带有 Cassandra 和 Elasticsearch)。
  • 数据库确实很重要,否则我不会问。每个数据库都有自己的额外功能。因此,对于 Janus 来说,编写一个自定义顶点程序可能是一个好主意。你如何匹配顶点?您使用的是长期运行的 OLAP 作业还是 OLTP 中短暂存在的东西?
  • @DanielKuppitz 感谢您的回复。在导入数据时,大部分匹配都是 OLTP 完成的,因为它需要尽快解决。我知道这将是一个手动操作(希望有一些 tinkerpop-api 功能)。但是因为导入是高度并发的,并且传入的数据可以与同一实体的所有顶点相关,我希望要删除的顶点可以在合并过程中获得新的属性或边。因此,如果我没有正确检查/锁定,我可能会丢失数据。我必须考虑一下这个......

标签: gremlin tinkerpop


【解决方案1】:

好的,如上面的 cmets 所述,您将在 OLTP 中进行匹配。这意味着您可能会有一个具体的切入点。让我们组成一个简单的示例图:

g = TinkerGraph.open().traversal()

// Stackoverflow data
g.addV("user").property("login", "user3508638").as("a").
  addV("user").property("login", "dkuppitz").property("age", 35).as("b").
  addV("question").property("title", "Tinkerpop/gremlin merge vertices (and edges)").as("c").
  addE("posted").from("a").to("c").
  addE("commented").from("b").to("c").property("time", 123).iterate()

// Github data
g.addV("user").property("login", "dkuppitz").property("name", "Daniel Kuppitz").as("a").
  addV("project").property("title", "TinkerPop").as("b").
  addE("contributed").from("a").to("b").iterate()

根据登录dkuppitz匹配顶点并将它们合并为单个用户顶点:

g.V().has("login", "dkuppitz").
  fold().filter(count(local).is(gt(1))).unfold().
  sideEffect(properties().group("p").by(key).by(value())).
  sideEffect(outE().group("o").by(label).by(project("p","iv").by(valueMap()).by(inV()).fold())).
  sideEffect(inE().group("i").by(label).by(project("p","ov").by(valueMap()).by(outV()).fold())).
  sideEffect(drop()).
  cap("p","o","i").as("poi").
  addV("user").as("u").
  sideEffect(
    select("poi").select("p").unfold().as("kv").
    select("u").property(select("kv").select(keys), select("kv").select(values))).
  sideEffect(
    select("poi").select("o").unfold().as("x").
    select("u").sideEffect { u ->
      u.path("x").getValue().each { x ->
        def e = u.get().addEdge(u.path("x").getKey(), x.get("iv"))
        x.get("p").each { p ->
          e.property(p.getKey(), p.getValue())
        }
      }
    }).
  sideEffect(
    select("poi").select("i").unfold().as("x").
    select("u").sideEffect { u ->
      u.path("x").getValue().each { x ->
        def e = x.get("ov").addEdge(u.path("x").getKey(), u.get())
        x.get("p").each { p ->
          e.property(p.getKey(), p.getValue())
        }
      }
    }).iterate()

我知道,查询非常复杂,尤其是对于深度嵌套的 lambda。但不幸的是,没有办法绕过 lambda,因为我们没有 addE(<traversal>) 重载(尽管我创建了 ticket)。无论如何,执行上面的查询后,图表如下所示:

gremlin> g.V().valueMap()
==>[login:[user3508638]]
==>[title:[Tinkerpop/gremlin merge vertices (and edges)]]
==>[title:[TinkerPop]]
==>[name:[Daniel Kuppitz],login:[dkuppitz],age:[35]]
gremlin> g.V().has("login", "dkuppitz").bothE()
==>e[19][15-commented->5]
==>e[20][15-contributed->12]
gremlin> g.V().has("login", "dkuppitz").bothE().valueMap(true)
==>[label:commented,time:123,id:19]
==>[label:contributed,id:20]

dkuppitz 两个顶点合并为一个(nameage 属性存在)并相应地重新创建了两条边。

更新:

使用TINKERPOP-1793,我们可以摆脱所有的 lambda:

g.V().has("login", "dkuppitz").
  fold().filter(count(local).is(gt(1))).unfold().
  sideEffect(properties().group("p").by(key).by(value())).
  sideEffect(outE().group("o").by(label).by(project("p","iv").by(valueMap()).by(inV()).fold())).
  sideEffect(inE().group("i").by(label).by(project("p","ov").by(valueMap()).by(outV()).fold())).
  sideEffect(drop()).
  cap("p","o","i").as("poi").
  addV("user").as("u").
  sideEffect(
    select("poi").select("p").unfold().as("kv").
    select("u").property(select("kv").select(keys), select("kv").select(values))).
  sideEffect(
    select("poi").select("o").unfold().as("x").select(values).
    unfold().addE(select("x").select(keys)).from(select("u")).to(select("iv"))).
  sideEffect(
    select("poi").select("i").unfold().as("x").select(values).
    unfold().addE(select("x").select(keys)).from(select("ov")).to(select("u"))).iterate()

【讨论】:

    猜你喜欢
    • 2019-05-14
    • 1970-01-01
    • 2021-02-28
    • 2019-01-14
    • 2021-04-20
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2023-01-15
    相关资源
    最近更新 更多