Gremlin / Bulbflow: Как выбрать узлы на основе их ребер и связанных свойств вершины
Извините за длинный пост, но я хочу избежать недоразумений по поводу того, что я ищу:)
В настоящее время я изучаю графовые базы данных и немного экспериментирую с bulbflow/neo4j. Таким образом, я пытаюсь использовать gremlin для большинства моих запросов, но я не знаю, выполним ли желаемый запрос или нет. Возможно, я даже ошибаюсь, пытаясь использовать graph db для такого случая, поэтому не стесняйтесь говорить мне, считаете ли вы, что я на правильном пути или нет.
Во-первых, позвольте мне предоставить немного контекста:
Я работаю над проектом с открытым исходным кодом на ранней стадии, который является компилятором для языка DSL, генерирующего C-код. В настоящее время мы планируем переписать все это на python по многим причинам (язык, перепроектирование, открытие для сообщества и т. Д.). Компилятор включает в себя то, что я назову кешем скомпилированных интерфейсов и шаблонов. Интерфейсы описывают шаблоны, и каждый шаблон связан с конфигурацией (список типизированных значений, связанных с переменными, описанными интерфейсами).
Цель запроса, который я хочу построить, состоит в том, чтобы выбрать реализацию одного шаблона в зависимости от входной конфигурации (фактически используемой в механизме генерации компилятора). В конце я хочу иметь возможность напрямую запрашивать через gremlin (если вообще возможно) единственный элемент, который я ищу, чтобы обеспечить уникальность для элементов, которые можно найти в этом "кэше". В настоящее время я вручную сопоставляю эту конфигурацию в коде python, но я хочу знать, возможно ли сделать это непосредственно в gremlin.
-
Итак, давайте определим пример графика для моего варианта использования: у нас есть три типа вершин:
- Def (определение), содержит свойство String с именем "signature", которое фактически является подписью шаблона, определенного этим узлом.
- Impl (реализация), содержащая два свойства, которые являются путями к исходному и предварительно скомпилированным файлам.
- Var (переменная), содержащая свойство String, которое является сигнатурой переменной.
Затем несколько видов ребер:
- Def -> impl_by -> Impl (для определения может существовать несколько реализаций, не содержащее никаких свойств)
- Impl -> select_by -> Var (Реализации могут быть выбраны через ограничение по значению переменной конфигурации, каждое ребро этого типа содержит фактически три свойства: тип, значение и ограничение - оператор сравнения -)
Край selected_by (или отношение, следующее за словарем bulflow) описывает ограничение выбора и, таким образом, имеет следующие свойства:
- val (значение, связанное с переменной для реализации источника)
- op (оператор сравнения, указывающий, какой тип сравнения сделать, чтобы ограничение было действительным или нет)
Это переводится как график, такой как (я опущу типы от краев selected_by на этом графике):
-- select_by { value="John", op="="} ---------
| \
(1)--Impl--- select_by { value=12, op=">"} ------ \
| \ \
| \ |- Var("name")
| |- select_by { value="Peter", op="="} -----------/
Def (2)--Impl-- \/
| |- select_by { value=15, op="<"} ---- /\
| \ / \
| |-/----|--- Var("ver")
(3)--Impl--- select_by { value="Kat", op="!="} ------/ /
| /
|--- select_by { value=9, op=">"} ---------/
Что я хочу сделать, это выбрать один (или несколько) Impl в зависимости от их отношений с Vars. Допустим, у меня есть конфигурация следующим образом:
Конфиг 1:
variable="name", value="Peter"
variable="ver", value=16
Это выберет Impl(3), поскольку Peter!= Kat AND 16 > 9, но не Impl(1), так как Peter!= John и Impl(2) с 16!< 15.
Я был заблокирован на нескольких уровнях, поэтому я начал задаваться вопросом, было ли это вообще возможно:
- Я не мог найти, как передать такие аргументы (конфигурацию) скрипту gremlin.
- Я не мог найти, как выбрать Impl на основе условий на исходящих ребрах.
Надеюсь, это не слишком запутанно.
Ура и спасибо!
РЕДАКТИРОВАТЬ:
Мне удалось заставить часть моего запроса работать с помощью многократного возврата и фильтров. Запрос (X - начальная вершина, VALUE - значение, которое я хочу сопоставить, и NAME - имя переменной для сопоставления) выглядит следующим образом:
Основа запроса:
g.v(X).out('impl').as('implem')
Повторите эту часть для каждой пары VALUE/NAME:
.out('select_by').filter{it.value=='VALUE'}
.inV('select_by').filter{it.name=='NAME'}
.back('implem')
Единственное, чего сейчас не хватает, так это того, что я не знаю, как использовать свойство 'op' края select_by, чтобы определить, как создать фильтр для использования. Например, есть случаи, когда я хочу в точности соответствовать конфигурации (и, таким образом, как в этом запросе, я игнорирую свойство 'op'), но есть случаи, когда я хочу принять во внимание свойство 'op', и используйте связанный фильтр в фильтрах.
Есть ли способ сделать это? (Или я должен отправить другой вопрос?)