Я продолжаю свою работу по расширению Gremlinator для поддержки большего подмножества запросов SPARQL. В нашей работе мы часто видим запросы SPARQL, подобные этим:
SELECT DISTINCT ?X ?Y ?Z ?V ?NAME
WHERE {
?X e:brother ?Z .
?Y e:brother ?V .
?Z v:name ?NAME .
?V v:name ?NAME .
FILTER (?X != ?Y) .
}
, который в основном говорит: Найти все X и Y, у которых есть братья с одинаковыми именами, где X не совпадает с Y. Можно подумать из SQL самостоятельного соединения. Пример здесь работает с Графом Богов.
Я придумал обход Гремлин, который нашел бы эти X и Y:
g.V().as("X").out("brother").as("Z").values("name").as("NAME1")
.V().as("Y").out("brother").as("V").values("name").as("NAME2")
.where("NAME1", P.eq("NAME2")).where("X", P.neq("Y")).select("X", "Y", "Z", "V", "NAME1", "NAME2");
, которые я затем попытался переписать в условия шага MATCH (для работы в существующей среде Gremlinator):
g.V().match(
__.as("START").V().as("X").out("brother").as("Z"),
__.as("START").V().as("Y").out("brother").as("V"),
__.as("Z").values("name").as("NAME"),
__.as("V").values("name").as("NAME"))
.where("X", P.neq("Y")).dedup("X", "Y", "Z", "V", "NAME").select("X", "Y", "Z", "V", "NAME");
Этот обход приводит к:
java.lang.IllegalArgumentException: Neither the sideEffects, map, nor path has a Y-key: WherePredicateStep(X,neq(Y))
, тогда как тот же запрос с добавленным шагом dedup () работает просто хорошо:
g.V().match(
__.as("START").V().as("X").out("brother").as("Z"),
__.as("START").V().as("Y").out("brother").as("V"),
__.as("Z").values("name").as("NAME"),
__.as("V").values("name").as("NAME"))
.dedup().where("X", P.neq("Y")).dedup("X", "Y", "Z", "V", "NAME").select("X", "Y", "Z", "V", "NAME");
Что я действительно хочу сделать, так это просто иметь предложение where внутри блока соответствия и не иметь никаких посторонних шагов dedup ().
g.V().match(
__.as("START").V().as("X").out("brother").as("Z"),
__.as("START").V().as("Y").out("brother").as("V"),
__.as("Z").values("name").as("NAME"),
__.as("V").values("name").as("NAME”),
__.where("X", P.neq("Y")))
.dedup("X", "Y", "Z", "V", "NAME").select("X", "Y", "Z", "V", "NAME");
Которые также выбрасывают та же ошибка, что и в других вариантах MATCH.
У меня есть идея добавить дополнительный шаг дедупликации из раздела F этой страницы: https://www.datastax.com/blog/2017/09/gremlin-recipes-9-pattern-matching, в котором упоминается предполагаемый виновник: TINKERPOP-1762 . Но, поскольку у меня установлена последняя версия Tinkerpop, похоже, эта проблема не имеет точно такой же причины, поскольку эта ошибка уже исправлена.