Gremlin Coalesce для добавления нескольких вершин и ребер
Прямо сейчас я могу сгенерировать запрос, чтобы создать столько вершин и ребер, сколько я хочу.
например
g.V().addV('vert1').as('a').addV('vert2').as('b').addE('has').from('a').to('b')
^^^^^^^^^^^^^ Это работает. Достаточно легко, верно? Теперь давайте создадим запрос gremlin, который создает эти вершины, только если их метка уникальна. Затем создайте грань между ними.
g.V().has(label,'vert1').fold().coalesce(unfold(),addV('vert1')).as('a').V().has(label,'vert2').fold().coalesce(unfold(),addV('vert2')).as('b').addE('has').from('a').to('b')
^^^^^^^^^^^^^ Это не работает
надеюсь, вы понимаете, что я пытаюсь сделать. Может кто-нибудь мне помочь?
Спасибо
2 ответа
У тебя есть fold()
который является ReducingBarrierStep
что следует после вашего шага метки на as('a')
и история пути к "а" теряется после этого шага. Вы можете прочитать больше об этом аспекте Gremlin здесь.
Вам просто нужно переписать свой запрос, чтобы учесть это - одним из способов может быть просто aggregate()
значение "а", а не просто название шага "а":
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.V().
......1> has(label,'vert1').fold().
......2> coalesce(unfold(),
......3> addV('vert1')).aggregate('a').
......4> V().has(label,'vert2').fold().
......5> coalesce(unfold(),
......6> addV('vert2')).as('b').
......7> select('a').unfold().
......8> addE('has').to('b')
==>e[2][0-has->1]
Если вам нужно вернуть все элементы, просто project()
возвращаемое ребро и трансформируем результаты по мере необходимости:
gremlin> g.V().
......1> has(label,'vert1').fold().
......2> coalesce(unfold(),
......3> addV('vert1')).aggregate('a').
......4> V().has(label,'vert2').fold().
......5> coalesce(unfold(),
......6> addV('vert2')).as('b').
......7> select('a').unfold().
......8> addE('has').to('b').
......9> project('e','in','out').
.....10> by().
.....11> by(inV()).
.....12> by(outV())
==>[e:e[2][0-has->1],in:v[1],out:v[0]]
Конечно, используя select()
в конце тоже не все так плохо:
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.V().
......1> has(label,'vert1').fold().
......2> coalesce(unfold(),
......3> addV('vert1')).aggregate('a').
......4> V().has(label,'vert2').fold().
......5> coalesce(unfold(),
......6> addV('vert2')).as('b').
......7> select('a').unfold().
......8> addE('has').to('b').as('x').
......9> select('a','b','x')
==>[a:[v[0]],b:v[1],x:e[2][0-has->1]]
Я тоже искал идемпотентный способ создать несколько вершин одной командой и получить результаты обратно. (Я использую API Gremlin Cosmos DB, и типичное решение, использующее складку...объединение...развертывание, не работает при объединении в цепочку.)
Путем некоторых экспериментов я придумал альтернативу, сложность которой линейна по мере добавления новых вершин. я используюinject()
искусственно создать «источник» для первого вызоваcoalesce()
.
g.inject("0")
.coalesce(__.V(['pk1','00']), addV('MyV')
.property('id','00')
.property('partitionKey','pk1')).as('x')
.coalesce(__.V(['pk1','01']), addV('MyV')
.property('id','01')
.property('partitionKey','pk1'))
.as('x')
.coalesce(__.V(['pk1','02']), addV('MyV')
.property('id','02')
.property('partitionKey','pk1'))
.as('x')
.select('x')
Для тех, кого не интересуют ключи разделов, это выглядит так:
g.inject("0")
.coalesce(__.V('00'), addV('MyV').property('id','00')).as('x')
.coalesce(__.V('01'), addV('MyV').property('id','01')).as('x')
.coalesce(__.V('02'), addV('MyV').property('id','02')).as('x')
.select('x')
Кроме того, мы можем одновременно создавать любое количество ребер между новыми вершинами, предоставляя уникальные метки (сas()
).
g.inject("0")
.coalesce(__.V(['pk2','05']), addV('MyV').property('id','05')
.property('partitionKey','pk2')
.property('ABC','123467890'))
.as('x').as('a')
.coalesce(__.V(['pk2','06']), addV('MyV').property('id','06')
.property('partitionKey','pk2')
.property('ABC','123467890'))
.as('x')
.coalesce(g.E(['pk2','07']), addE('MyE').property('id','07').from('a'))
.as('x')
.select('x')