Как переместить край в Гремлине

Я новичок в Gremlin и работаю с машинописным текстом в Azure Cosmos DB, а это значит, что мне не разрешено использовать все интересные новые функции, такие как sideEffect ...

У меня есть древовидный сценарий, в котором вершины являются родительскими по отношению к другим вершинам, но могут иметь только одного собственного родителя и человека, который работает в одной вершине.

Вот несколько примеров данных для моего графика:

g.addV('person').property('partitionKey', 'person').property('accountID','1')
g.addV('unit').property('partitionKey', 'unit').property('unitID', '1')
g.addV('unit').property('partitionKey', 'unit').property('unitID', '2')
g.addV('unit').property('partitionKey', 'unit').property('unitID', '3')
g.V().has('accountID','1').as('p').V().has('unitID','1').addE('employedAt').from('p')
g.V().has('unitID','1').as('u').V().has('unitID','2').addE('parentOf').from('u')
g.V().has('unitID','2').as('u').V().has('unitID','3').addE('parentOf').from('u')

Теперь дерево выглядит так:

человек --- employeeAt --- ›unit1 --- parentOf ---› unit2 --- parentOf --- ›unit3

Теперь мы хотим сделать unit2 дочерним по отношению к unit3.

Ожидаемый результат после этого:

человек --- employeeAt --- ›unit1 --- parentOf ---› unit3 --- parentOf --- ›unit2

Теперь мы хотим переместить одну вершину (создав новый входящий parentOf-Edge и отбросив старую).

Первый блок - проверить, есть ли у человека доступ к обеим вершинам. Это не очень эффективно, но я не знаю, как это сделать лучше.

Первое выражение в coalesce - переместить вершину вниз по дереву (сделать ее дочерней по отношению к одной из его подчиненных вершин). Поэтому мы проверяем, является ли он родителем targetVertex, когда он является родителем, тогда он также выполняет остальную часть этого оператора coalesce.

Второе утверждение - переместить вершину в другую ветвь дерева. Это будет достигнуто, когда это не будет трудной частью.

// Get the employedAtVertex and store the employedAtVertex
    g.V().has('person', 'accountID', accountID).outE('employedAt').otherV().as('employedAtVertex')
// Check if the employedAtVertex is parentOf the movingVertex and store the movingVertex
    .V().has('id', movingVertexID).as('movingVertex').until(select('employedAtVertex')).repeat(__.in('parentOf'))
// Check if the employedAtVertex is parentOf the targetVertex and store the targetVertex
    .V().has('id', targetVertexID).as('targetVertex').until(select('employedAtVertex')).repeat(__.in('parentOf'))

// ### Coalesce-Step (do the first part if possible, otherwise do the second part)
    .coalesce(
// ### First Part: Make a vertex the children of his own children
// Check if the movingVertex is parentOf the targetVertex
    select('targetVertex').until(has('id', select('movingVertex').values('id'))).repeat(__.in('parentOf'))
// Union the incoming parentOf-Edges in moving- and targetVertex and store them as edgesToDrop
 .union(select('movingVertex').inE().hasLabel('parentOf'),select('targetVertex').inE().hasLabel('parentOf')).as('edgesToDrop')
// Check if the employedAtVertex is parentOf the old parent of the movingVertex and store it as oldParentVertex
    .V().has('id', oldParentOfMovingVertexID).as('oldParentVertex').until(select('employedAtVertex')).repeat(__.in('parentOf'))
// Create parentOf-Edge from oldParentVertex to targetVertex
    .select('targetVertex').addE('parentOf').from('oldParentVertex')
// Create parentOf-Edge from targetVertex to movingVertex
    .select('movingVertex').addE('parentOf').from('targetVertex'),

// ### Second Part: Make a vertex the children of a vertex higher in the tree or in an other branch
// Get the incoming edge in movingVertex and store it as edgesToDrop
    select('movingVertex').inE('parentOf').as('edgesToDrop')
// Create parentOf-Edge from targetVertex to movingVertex
    .select('movingVertex').addE('parentOf').from('targetVertex'))
// ### Ende of Coalesce

// Drop the stored edgesToDrop
    .select('edgesToDrop').drop()

У меня сейчас несколько проблем:

  1. То, как я пытаюсь бросить, не работает
  2. Когда я удаляю оператор drop, он дважды создает (в первом случае слияния) оба края, что для меня совершенно не имеет смысла.
  3. Есть ли более эффективный способ проверить, является ли usedAt-Vertex родительским (или прародителем или кем-то еще) движущейся и целевой вершины?

person Tobi Hin    schedule 30.06.2020    source источник
comment
поскольку это сложный вариант использования, я думаю, будет лучше, если вы добавите скрипт для генерации данных примера или сохраненного примера gremlify. а затем задайте ожидаемое поведение для этих данных.   -  person noam621    schedule 01.07.2020
comment
Привет, спасибо, что объяснили, как получить помощь. Я обновил свой вопрос и добавил пример, а также ожидаемый результат   -  person Tobi Hin    schedule 02.07.2020


Ответы (2)


Я попытался понять логику вашего запроса и примера, надеюсь, это то, что вам нужно.

g.V().has('person', 'accountID', accountID).
  out('employedAt').as('employedAtVertex').

// Check if the employedAtVertex is parentOf the movingVertex and targetVertex
  emit(has('unitID', within(movingVertexID, targetVertexID))).
  repeat(out('parentOf')).
  fold().where(count(local).is(2)).as('vertices').
  unfold().has('unitID', targetVertexID).as('targetVertex').

// Check if the movingVertex is parentOf the targetVertex
  choose(until(has('unitID', movingVertexID)).repeat(__.in('parentOf')),

// ### First Part: Make a vertex the children of his own children
        select('vertices').unfold().has('unitID', movingVertexID).as('movingVertex')
        union(            
            __.in('parentOf').addE('parentOf').to(select('movingVertex').out('parentOf')),
                bothE('parentOf').drop(),
                addE('parentOf').from('targetVertex')
            ),
// ### Second Part: Make a vertex the children of a vertex higher in the tree or in an other branch
        union(
            inE('parentOf').drop(),
            addE('parentOf').from('targetVertex'),
            )
    )
  

пример: https://gremlify.com/fuq7sbmvjzv

person noam621    schedule 02.07.2020

Первая часть работает отлично. и результат выглядит ожидаемым.

У меня сейчас проблема со второй частью. Когда я создаю дерево, которое выглядит так:

     person
       |
   employedAt
       |
      unit1
     /     \
parentOf  parentOf
   |         |
unit2      unit4
   |
parentOf
   |
unit3

и ich теперь хотят переместить unit2 в дочерний для unit4, это не работает. У меня есть unitID 2 для movingVertex и unitID 4 для targetVertex

Ожидаемый результат будет таким:

person
   |
employedAt
   |
unit1
   |
parentOf
   |
unit4
   |
parentOf
   |
unit2
   |
parentOf
   |
unit3

Но ничего не делает.

person Tobi Hin    schedule 03.07.2020