Создайте запрос Gremlin addEdge (), который не будет дублироваться для 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>  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]

person brettu    schedule 12.09.2013    source источник


Ответы (2)


Чтобы замкнуть цикл здесь, ответ на этот вопрос был дан в списке рассылки Aurelius Graphs. По сути:

мы действительно не видим варианта использования ограничений уникальности для применения к парам вершин (а-ля - только одно ребро может существовать между вершинами A и B) по следующим причинам:

  • в большинстве случаев вы можете довольно дешево избавиться от дублирования на стороне запроса с помощью dedup (): v.out ('follow'). dedup () .....
  • вероятность конфликта намного ниже (из-за N ^ 2 комбинаций вершин), что делает блокировки просто слишком дорогими по сравнению с вероятностью конфликта.

Короче говоря, вы должны проверить наличие края в своем приложении, поскольку Titan не может его принудительно применить.

person stephen mallette    schedule 16.09.2013
comment
Идемпотентные обновления являются неотъемлемой частью распределенных систем. Дедуп работает ... до тех пор, пока вы не измените край 1000 раз (например, измените вес), а затем начнется массовая утечка ресурсов. - person Paul S; 25.10.2019

Это предотвращает дублирование кода приложения по сравнению с конфигурацией БД и решает возникшую у нас проблему.

   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
person brettu    schedule 16.09.2013