Обход цепочки Java API GremlinPipeLine в случаях использования графа Titan
У меня есть случай, когда мне нужно пройти через цепочку вершин, начиная с определенной вершины. Это линейная цепочка (как поезд) с единственной вершиной, соединенной с предыдущей. При прохождении я должен испускать определенные вершины по некоторым критериям, пока не достигну конца цепочки.
Второй вариант использования является расширением вышеприведенного варианта использования, но вместо одной цепочки, начинающейся с одной вершины, существует несколько таких цепочек, снова начиная с одной вершины. Я должен пройти каждую цепочку и проверить наличие определенного значения свойства в вершинах. Когда совпадение этого свойства найдено, я должен испустить эту вершину и начать со второй цепочки и так далее.
Я должен добиться этого с помощью Gremlin Java API. Это кажется простым, но я новичок в gremlin, и в интернете не так много помощи от gremlin java API.
1 ответ
Преобразование Gremlin Groovy в Gremlin Java не должно быть очень сложным. Я бы всегда возражал против этого, как вы:
- Значительно увеличьте размер вашего кода
- Сделайте ваш код менее читабельным
- Сделайте ваш код сложнее поддерживать
Если вы работаете в "магазине Java", который не слышит о внешнем языке программирования, я думаю, что не так уж сложно продавать людей по этим вопросам, лишь с несколькими примерами различий, которые Gremlin имеет в groovy и java (легко прочитайте одну строку против того, что может быть сотнями строк кода). Более того, Groovy может вписаться в стандартный проект Maven либо вместе с Java в том же модуле, либо в отдельном автономном модуле, от которого зависят другие проекты. В большинстве случаев я предпочитаю последний вариант, так как вы изолируете ваш groovy в одном пакете, и он становится многократно используемым в качестве DSL для нескольких случаев использования (например, приложение, дополнительная библиотека в консоли gremlin и т. Д.).
Тем не менее, если вы все еще должны использовать Java, я все равно начал бы с написания Groovy. Используйте консоль Gremlin и получите правильный алгоритм обхода. Похоже, что оба ваших варианта использования включают в себя циклы, поэтому мы просто скажем, что ваш обход выглядит примерно так:
g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
Так что это будет проходить цепочку от вершины "1" до тех пор, пока я не исчерпаю цепочку, обозначенную "истиной" в первом замыкании, а затем испущу любую вершину, которая соответствует моим критериям во втором замыкании. Как только вы определите и протестируете большую часть своего Gremlin, пора переходить на Java.
Как вы знаете, это начинается с GremlinPipeline
и первая часть довольно проста для конвертации:
new GremlinPipeline(g.getVertex(1)).out()
Как вы можете видеть, подход Groovy будет довольно четко отображаться на Java, пока вы не дойдете до точки, где вам нужно закрытие и loop
это один из тех шагов, который требует одного. Для работы с Gremlin Java вам, вероятно, будет полезно взглянуть на javadoc для GremlinPipeline
,
Я использовал версию с тремя аргументами loop
- тот, который помечен как "устарел" (но это нормально для наших целей) - вы можете увидеть его здесь. Первый аргумент прост - целое число, поэтому первая часть перевода:
new GremlinPipeline(g.getVertex(1)).out().loop(1, closure, closure)
Я оставил заполнители для двух других замыканий, которые у нас есть. Если вы посмотрите на это так, то оно на самом деле ничем не отличается от нашей версии Groovy - даже немного другой синтаксис.
До Java 8 не было понятия о замыканиях, встроенных в Java-язык. Обратите внимание, что в TinkerPop3 Gremlin кардинально изменился, чтобы использовать тот факт, что у нас теперь есть лямбды. Но, как вы находитесь в TinkerPop2, вы должны использовать встроенный в PipeFunction
который по существу представляет типизированные версии наших заводных замыканий. PipeFunction
для обоих аргументов цикла это:
PipeFunction<LoopPipe.LoopBundle<E>,Boolean>
Так что в основном это функция, которая получает LoopPipe.LoopBundle
как объект, который содержит метаданные о цикле и ожидает, что вы вернете логическое значение. Если вы понимаете эту концепцию, тогда вся Gremlin Java открывается для вас, потому что везде, где вы видите замысловатое замыкание, вы знаете, что под ним просто какая-то форма PipeFunction
в Java и учитывая, что теперь вы можете прочитать ожидания PipeFunction
из Javadocs, это должно быть просто сделать эти языковые переводы.
Первый заключительный перевод, который мы должны сделать, прост и понятен - нам просто нужно наше PipeFunction
возвращать true
:
new GremlinPipeline(g.getVertex(1)).out().loop(1,
new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
return true;
}
}, closure)
Итак, для второго аргумента loop
мы должны построить новый PipeFunction
, который имеет один метод с именем compute
, Из этого метода мы возвращаемся true
, Теперь справиться со вторым PipeFunction
Аргумент, управляющий вершинами для излучения:
new GremlinPipeline(g.getVertex(1)).out().loop(1,
new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
return true;
}
},
new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
return argument.getObject().getProperty("someProperty").equals("emitIfThis");
}
})
И там стоит преобразование. Поскольку это длинный пост, давайте поместим исходный groovy ближе к описанному выше, чтобы разница была очевидна:
g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
Мы перешли от приведенной выше одной строки кода к почти дюжине, что было очень простым обходом. Gremlin Java вступает в свои права в TinkerPop3 с учетом лямбд и капитального пересмотра самого языка, но в этих предыдущих версиях создается Java-код, который действительно не стоит того, чтобы его генерировать или поддерживать, когда Groovy может сделать вещи очень аккуратными и аккуратными.