6

有没有办法在 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]

设置 unique(IN|BOTH|OUT) 会产生一个问题,即每个用户只能有一个关注者。这当然会使用户 -> 关注 -> [users] 关系变得不可能。

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

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]
4

2 回答 2

7

为了在这里结束循环, Aurelius Graphs Mailing List中回答了这个问题。基本上:

由于以下原因,我们并没有真正看到将唯一性约束应用于顶点对(a la - 顶点 A 和 B 之间只能存在一条边)的用例:

  • 大多数时候,您可以使用 dedup(): v.out('follows').dedup().....
  • 冲突的可能性要低得多(由于顶点的 N ^ 2 个组合),这使得与冲突的可能性相比,锁变得非常昂贵。

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

于 2013-09-16T11:13:08.023 回答
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
于 2013-09-16T18:13:43.697 回答