首页 文章

创建一个不会重复Titan的addEdge()Gremlin查询

提问于
浏览
5

有没有办法在Titan图上的两个顶点之间创建一个唯一的边,并确认无法再次创建它,除非删除并重新创建?

基本上我需要创建:

vertex1--follows-->vertex2

但我继续为同一个关系创建多个边:

vertex1--follows-->vertex2
vertex1--follows-->vertex2
vertex1--follows-->vertex2
vertex1--follows-->vertex2

我的基本addEdge查询是这样的:

def follow(target)
  grem = "g.addEdge(
    g.V('id', '#{id}').next(),
    g.V('id', '#{target.id}').next(),
    'follows',
    [since:#{Time.now.year}]
  )"

  $graph.execute(grem).results
end

我想要找到的是这样的

def follow(target)
  grem = "g.addEdge(
    g.V('id', '#{id}').next(),
    g.V('id', '#{target.id}').next(),
    'follows',
    [since:#{Time.now.year}]
  ).unique(Direction.OUT)"

  $graph.execute(grem).results
end

在这个文档中有一个名为unique的方法,但我似乎无法在边缘上工作,只能在顶点属性上工作 .

https://github.com/thinkaurelius/titan/wiki/Type-Definition-Overview

我可以在创建addEdge之前运行查询以检查现有边缘,但这看起来很麻烦并且可能导致竞争条件问题 .

是否有可能存在一个方法,我可以附加到addEdge,如果边缘已存在,将阻止创建重复边缘?

或者,有没有办法在边缘创建一个独特的属性标签?

这是问题的一个gremlin会话:

gremlin>  g.makeType().name('follows').unique(IN).makeEdgeLabel();
==>v[36028797018964558]
gremlin> u = g.addVertex([name:'brett'])
==>v[120004]
gremlin> u2 = g.addVertex([name:'brettU'])
==>v[120008]
gremlin> e = g.addEdge(u, u2, 'follows')
==>e[2w5N-vdy-2F0LaTPQK2][120004-follows->120008]
gremlin> e = g.addEdge(u, u2, 'follows')
An edge with the given type already exists on the in-vertex
Display stack trace? [yN] 
gremlin> e = g.addEdge(u2, u, 'follows')
==>e[2w5P-vdC-2F0LaTPQK2][120008-follows->120004]
gremlin> u3 = g.addVertex([name:'brett3'])
==>v[120012]
gremlin> e = g.addEdge(u3, u, 'follows')
An edge with the given type already exists on the in-vertex
Display stack trace? [yN] N
gremlin> g.E
==>e[2w5N-vdy-2F0LaTPQK2][120004-follows->120008]
==>e[2w5P-vdC-2F0LaTPQK2][120008-follows->120004]

设置唯一(IN | BOTH | OUT)会产生一个问题,即每个用户只能有一个关注者 . 这当然会让用户无法 - >跟随 - > [用户]关系 .

这是尝试在边缘上设置唯一属性的另一个示例,这也失败了:

gremlin> g.makeType().name('follows_id').unique(BOTH).makeEdgeLabel();
==>v[36028797018964942]
gremlin>  u = g.addVertex([name:'brett'])
==>v[200004]
gremlin>  u2 = g.addVertex([name:'brett2'])
==>v[200008]
gremlin>  u3 = g.addVertex([name:'brett3'])
==>v[200012]
gremlin> e = g.addEdge(u, u2, 'follows', [follows_id:'200004-20008'])
Value must be a vertex
Display stack trace? [yN] N
gremlin> g.E
==>e[4c9z-Q1S-2F0LaTPQQu][200004-follows->200008]
gremlin> e = g.addEdge(u, u2, 'follows', [follows_id:'200004-20008'])
Value must be a vertex
Display stack trace? [yN] N
gremlin> g.E
==>e[4c9z-Q1S-2F0LaTPQQu][200004-follows->200008]
==>e[4c9B-Q1S-2F0LaTPQQu][200004-follows->200008]

2 回答

  • 7

    要在这里关闭循环,这个问题在Aurelius Graphs Mailing List中得到了解答 . 基本上:

    我们并没有真正看到应用于顶点对的唯一性约束的用例(由于这些原因,在顶点A和B之间只存在一条边):大多数情况下,你可以完全摆脱重复在查询方面廉价地使用重复数据删除():v.out('跟随') . 重复数据删除()......冲突的可能性要低得多(由于顶点的N ^ 2组合),这使得锁定只是与冲突的可能性相比,waaaay更贵 .

    简而言之,您应该在应用程序中验证边缘存在,因为Titan无法强制执行 .

  • 0

    这可以防止应用程序代码与数据库配置重复,并解决我们遇到的问题 .

    grem = "
          if(g.V('uid', '#{id}').out('follows').has('id', g.V('uid', '#{target.id}').next().id).hasNext() == true){
            println 'already connected'
          } else{
            g.addEdge(
              g.V('uid', '#{id}').next(),
              g.V('uid', '#{target.id}').next(),
              'follows',
              [since:(new java.util.Date()).getTime()]
            )
          }"
        $graph.execute(grem).results
    

相关问题