Гремлин - Упор вершины не работает с объединением - PullRequest
2 голосов
/ 01 мая 2020

Я новичок в gremlin и имею очень простой случай, когда мне нужно проверить это:

  • Если вершина существует
    • Обновить свойства
  • Иначе
    • Добавить вершину со свойствами

Для этого я использую Java API.

Мой код:

g.V().hasLabel("Entity").has("identifier", "123").fold()
.coalesce(
    __.unfold(),
    __.addV("Entity")
        .property("identifier", "123")
        .property("value", "A")
        .property("action", "add")
    )
.property("value", "A")
.property("action", "update")
.iterate();

Я знаю, что это очень простой случай, и я сослался на пример, приведенный в [ График CosmosDB: шаблон запроса "upsert"

Но это не работает. Если вершина не существует, она добавляется со свойствами, но свойства также обновляются.

Ответы [ 2 ]

2 голосов
/ 01 мая 2020

Когда вы пишете Gremlin, вам нужно думать о потоках. V() создает поток всех вершин в графе. Представьте, что каждый элемент в этом потоке, попадающий в фильтры hasLabel() и has(), должен быть спарен до тех пор, пока они не достигнут шага сокращения fold(), в результате которого получается List с вершинами, которые соответствуют критериям фильтра, или, если их нет, он simple создает пустой список, который становится новым объектом в потоке.

Оттуда coalesce() создает случай типа if-then, когда первый предоставленный ему дочерний поток, возвращающий значение, заканчивается, а остальные дочерние потоки игнорируются. Следовательно, если unfold(), который принимает List с вершинами, созданными fold(), содержит вершину, то он передается потоку, и эта вершина существует, и, таким образом, coalesce() создает эту существующую вершину и переходит к последним двум шаги property("value", "A").property("action", "update"). Если List пуст, то поток unfold() не создает объектов и переходит к следующему дочернему потоку, который начинается с addV(). Поток addV(), очевидно, создаст новый Vertex с указанными свойствами, но затем coalesce() в качестве его родителя создаст эту вновь добавленную вершину в потоке, и он также перейдет к этим двум последним шагам и перезапишет свойство значения, которые вы указали для addV().

Если вы хотите иметь два отдельных пути, то вы можете сделать что-то вроде этого:

g.V().hasLabel("Entity").has("identifier", "123").fold()
.coalesce((Traversal)
    __.unfold()
        .property("value", "A")
        .property("action", "update"),
    __.addV("Entity")
        .property("identifier", "123")
        .property("value", "A")
        .property("action", "add")
    )
.iterate();
1 голос
/ 01 мая 2020

Независимо от того, существует ли вершина или нет, объединение вернет существующую или вновь созданную вершину. В любом случае шаги настройки свойства, которые следуют после объединения, будут применены ко всему, что вытекает из него. Если вы хотите, чтобы изменения после объединения были применены к существующей вершине, поместите их после шага разворачивания.

...