TP3: обход Gremlin и удаленное добавление ребер с помощью Java-клиента

Я хотел бы знать, есть ли простой способ добавления ребер к удаленному графу из программы Java. В настоящее время у меня есть:

  • экземпляр запущенного сервера Gremlin (TP 3.0.0.M7), который позволяет подключаться к графу Neo4j. gremlin-server.sh -i com.tinkerpop neo4j-gremlin 3.0.0.M7 был выполнен заранее, а сервер запущен с gremlin-server.sh conf/remote-objects.yaml
  • приложение Java, содержащее Client объект, который к нему подключается.

Насколько мне известно, приложение Java может взаимодействовать с сервером только путем отправки запросов Gremlin через метод client.submitAsync() (верно?).

Моя проблема заключается в следующем: Я бы нашел две вершины, и, если они обе существуют, создать границу между ними. Если бы сам объект Graph был доступен в моем приложении Java, это было бы так же просто, как и в локальной консоли Gremlin. Я бы просто написал Java-эквивалент

gremlin> v = g.addVertex('name', 'Hank')
==>v[16]
gremlin> v2 = g.addVertex('name', 'Pete')
==>v[18]
gremlin> v.addEdge('knows', v2)
==>e[20][16-knows->18]
gremlin>

Добавить ребро к графу на удаленном сервере сложнее, так как мне нужно сначала найти две вершины, прежде чем добавлять ребро между ними. Мой код Java для этого выглядит следующим образом:

//The params object is a Map that binds `fromParam` and `toParam` to strings Hank and Pete, respectively
ResultSet r = client.submitAsync("g.V().has('name', fromParam)", params).get();
ResultSet r2 = client.submitAsync("g.V().has('name', toParam)", params).get();

Это возвращает мне два DetachedVertex объекта. Третий запрос на добавление ребра между ними:

// outVertex and inVertex are the DetachedVertex objects added to params
ResultSet r3 = client.submitAsync("outVertex.attach(g).addEdge('knows', inVertex.attach(g))", params).get();

Похоже, это сработало, но я поставил меня в тупик на пару часов и кажется огромной проблемой для такой элементарной операции. Поэтому мои вопросы заключаются в следующем:

  • Есть ли запрос Gremlin, который может объединить эти три запроса? Т.е. Могу ли я найти и добавить ребро между двумя несвязанными вершинами в одном запросе?
  • Или существует ли способ для программы Java достичь удаленного объекта Graph, как если бы он был локальным?

person rvw    schedule 11.02.2015    source источник
comment
Что произойдет, если вы отправите всю задачу (как поиск, так и добавление ребер) в виде одного запроса: g.V('name', 'Hank').addEdge('knows', g.V('name', 'Pete'))?   -  person Faber    schedule 11.02.2015
comment
Я имел в виду: g.V('name', 'Hank').next().addEdge('knows', g.V('name', 'Pete').next())   -  person Faber    schedule 11.02.2015
comment
Я никогда не понимал, что использование g.V() дважды в одном запросе допустимо! Я полагаю, добавление некоторых count() шагов также позволяет проверять наличие дубликатов. Да, и это должно быть g.V().has('name', 'Hank') вместо g.V('name', 'Hank'), но это легко исправить :) Приветствую. Ответ на мой второй вопрос, наверное, нет, верно?   -  person rvw    schedule 12.02.2015
comment
В консоли gremlin вы можете написать g.V('name', 'Hank') вместо g.V().has('name', 'Hank'), не знаю, работает ли это также с вашим подходом удаленного доступа. Я предполагаю, что первый вариант более эффективен, если вы создали индекс для «имени». Последний всегда перебирает все вершины, чего вы не хотите делать. См. Gremlindocs: gremlindocs.com/#transform/v   -  person Faber    schedule 12.02.2015
comment
Я работаю с Tinkerpop3, где этого больше нет. Насколько мне известно, gremlindocs.com был написан для TP2, и найдена единственная документация по обходам в TP3. здесь.   -  person rvw    schedule 12.02.2015


Ответы (1)


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

Однако в настоящее время мы работаем над тем, чтобы сделать это проще, но пока вы также можете сделать это (если вам нужен однострочный):

g.V().has('name', fromParam).as('from').map {
    g.V().has('name', toParam).tryNext().orElse(false)
}.is(neq, false).addInE('knows', 'from')

В следующем примере показано, как этот подход работает для существующих и несуществующих вершин:

gremlin> g = TinkerFactory.createModern()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.V().has("name","marko").out("created")
==>v[3]
gremlin> g.V().has("name","marko").as("from").map {
             g.V().has("name", "riple").tryNext().orElse(false)
         }.is(neq, false).addInE("created", "from") // riple doesn't exist, hence no edge is being created
gremlin> g.V().has("name","marko").out("created")
==>v[3]
gremlin> g.V().has("name","marko").as("from").map {
             g.V().has("name", "ripple").tryNext().orElse(false)
         }.is(neq, false).addInE("created", "from") // ripple does exist, hence a new edge is being created
==>v[5]
gremlin> g.V().has("name","marko").out("created")
==>v[3]
==>v[5]
person Daniel Kuppitz    schedule 11.02.2015
comment
У меня этот запрос не работает, кажется, на шаге tryGet() не работает. Этот конкретный шаг не отображается в документации TP3, откуда вы это взяли? Изолированный запрос g.V().has('name', 'Hank').tryGet() всегда возвращает пустой набор в консоли Gremlin, которую я экспериментировал. В полном запросе клиент в java выдает исключение MissingMethodException для добавленного метода is(), а консоль выдает мне ошибку com.tinkerpop.gremlin.process.graph.util.DefaultGraphTraversal cannot be cast to com.tinkerpop.gremlin.structure.Element. - person rvw; 12.02.2015
comment
Извините, только что исправили опечатку, должно быть tryNext(). - person Daniel Kuppitz; 12.02.2015
comment
Ура, имеет смысл. Мы приближаемся! Вплоть до orElse(false) запрос работает и извлекает вершину, если она найдена, и false в противном случае. Однако результат шага is(neq, false) не работает. Если вершина найдена, ничего не возвращается (что делает невозможным продолжение шага addEdge(), и если вершина не найдена, я получаю java.lang.Boolean cannot be cast to com.tinkerpop.gremlin.structure.Element ошибку. - person rvw; 12.02.2015
comment
(Кстати, технически @Faber мне уже предоставил рабочее решение, но не в качестве ответа. Я не совсем уверен, как действовать дальше с точки зрения принятия / голосования, так как я также очень заинтересован в том, чтобы ваш запрос работает ...!) - person rvw; 12.02.2015
comment
Дело в том, что вы не можете создать ребро, если другая вершина не найдена, отсюда и фильтр .is(neq, false). Я что-то не так понял? Я добавил в свой ответ более крупный пример. - person Daniel Kuppitz; 12.02.2015
comment
Какую версию TP вы используете? В моей консоли Gremlin 3.0.0.M7 ваши запросы последовательно (независимо от наличия пульсации / ряби) дают мне ошибку No signature of method: com.tinkerpop.gremlin.process.graph.util.DefaultGraphTraversal.is() is applicable for argument types: (com.tinkerpop.gremlin.structure.Compare$2, java.lang.Boolean) values: [neq, false]. - person rvw; 12.02.2015
comment
Ах, надо было упомянуть, это текущий снимок. См .: tinkerpop.com/docs/3.0.0-SNAPSHOT/# is-step - person Daniel Kuppitz; 12.02.2015