Neo4j: как передать переменную в свойство Neo4j Apoc (apoc.path.subgraphAll)
Я новичок в Neo4j и пытаюсь сделать POC, реализовав графическую базу данных для корпоративной справочной / интеграционной архитектуры (архитектура, в которой все корпоративные приложения представлены в виде узлов, базовые таблицы / API - логически сгруппированы в виде узлов, интеграции между приложениями в виде отношений.
Цель состоит в том, чтобы беспрепятственно выполнить "Анализ воздействия", используя преимущества Graph DB (Примечание: я понимаю, что это может быть неправильным подходом для достижения того, что я пытаюсь достичь, поэтому предложения приветствуются)
Позвольте мне кратко ответить на мой вопрос,
Есть четыре приложения - A1, A2, A3, A4; A1 имеет набор таблиц (представленных узлом A1TS1), который обновляется интеграцией 1 (отношения в данном случае), и тот же набор таблиц считывается интеграцией 2. Таким образом, модель данных выглядит следующим образом
(A1TS1)<-[:INT1]-(A1)<-[:INT1]-(A2)
(A1TS1)-[:INT2]->(A1)-[:INT2]->(A4)
У меня есть имена таблиц базовых приложений, захваченных как свойство List в узле A1TS1.
Допустим, одна таблица приложения изменена для нового столбца или типа данных, и я хотел понять все затронутые интеграции и приложения. Теперь я пытаюсь написать запрос, как показано ниже, чтобы извлечь все узлы и отношения, которые связаны / затронуты из-за этого изменения таблицы, но не в состоянии этого достичь
Ожидаемый результат - все затронутые узлы (A1TS1, A1, A2, A4) и отношения (INT1, INT2)
Вариант 1 (с использованием APOC)
MATCH (a {TCName:'A1TS1',AppName:'A1'})-[r]-(b)
WITH a as STRTND, Collect(type(r)) as allr
CALL apoc.path.subgraphAll(STRTND, {relationshipFilter:allr}) YIELD nodes, relationships
RETURN nodes, relationships
Это сбой с ошибкой Failed to invoke procedure 'apoc.path.subgraphAll': Caused by: java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String
Вариант 2 (Использование с, раскрутить, собирать предложение)
MATCH (a {TCName:'A1TS1',AppName:'A1'})-[r]-(b)
WITH a as STRTND, Collect(r) as allr
UNWIND allr as rels
MATCH p=()-[rels]-()-[rels]-()
RETURN p
Это приводит к ошибке "Невозможно использовать одну и ту же переменную отношения" rels "для нескольких шаблонов", но если я использую [rels] один раз, как p=()-[rels]=()
это работает, но не дает мне все узлы
Любая помощь / предложение / руководство приветствуется. заранее спасибо
ОбновлениеПопытка дать больше контекста, показывая основные данные
MATCH (TC:TBLCON) RETURN TC
"TC"
{"Tables":["TBL1","TBL2","TBL3"],"TCName":"A1TS1","AppName":"A1"}
{"Tables":["TBL4","TBL1"],"TCName":"A2TS1","AppName":"A2"}
MATCH (A:App) RETURN A
"A"
{"Sponsor":"XY","Platform":"Oracle","TechOwnr":"VV","Version":"12","Tags":["ERP","OracleEBS","FinanceSystem"],"AppName":"A1"}
{"Sponsor":"CC","Platform":"Teradata","TechOwnr":"RZ","Tags":["EDW","DataWarehouse"],"AppName":"A2"}
MATCH ()-[r]-() RETURN distinct r.relname
"r.relname"
"FINREP" │ (runs between A1 to other apps)
"UPFRNT" │ (runs between A2 to different Salesforce App)
"INVOICE" │ (runs between A1 to other apps)
Это то, что я пытаюсь достичь. Предположим, что "TBL3" изменяется в приложении A1, я хотел написать запрос с указанием таблицы "TBL3" в шаблоне соответствия, получить все связанные отношения и связанные узлы (в восходящем направлении).
Может быть, мне нужно выполнить 3 шага, Шаг 1 - Написать шаблон соответствия, чтобы найти начальный узел и связанные отношения Шаг 2 - Сохранить эти отношения из шага 1 в переменной / параметре Array Шаг 3 - Пропустить начальный узел с шага 1 и параметр с шага 2 до apoc.path.subgraphAll, чтобы увидеть все затронутые узлы
Концептуально это может показаться обоснованным, но вопрос о том, как сделать это технически в запросе neo4j Cypher, является вопросом.
Надеюсь это поможет
2 ответа
С ответом киберзамка следующий запрос дает мне то, что я хочу. Единственным ограничением является то, что этот результат ограничен 3 слоями (3-й уровень через опциональное соответствие)
MATCH (TC:TBLCON) WHERE 'TBL3' IN TC.Tables
CALL apoc.path.subgraphAll(TC, {maxLevel:1}) YIELD nodes AS invN, relationships AS invR
WITH TC, REDUCE (tmpL=[], tmpr IN invR | tmpL+type(tmpr)) AS impR
MATCH FLP=(TC)-[]-()-[FLR]-(SL) WHERE type(FLR) IN impR
WITH FLP, TC, SL,impR
OPTIONAL MATCH SLP=(SL)-[SLR]-() WHERE type(SLR) IN impR RETURN FLP,SLP
Это работает для моих нужд, надеюсь, это также может кому-то помочь.
Спасибо всем за ответы и предложения
****Обновить****
Улучшен запрос, чтобы избавиться от необязательных критериев соответствия и других заданных ограничений.
MATCH (initTC:TBLCON) WHERE $TL IN initTC.Tables
WITH Reduce(O="",OO in Reduce (I=[], II in collect(apoc.node.relationship.types(initTC)) | I+II) | O+OO+"|") as RF
MATCH (TC:TBLCON) WHERE $TL IN TC.Tables
CALL apoc.path.subgraphAll(TC,{relationshipFilter:RF}) YIELD nodes, relationships
RETURN nodes, relationships
Спасибо всем (особенно киберсам)
Этот запрос может делать то, что вы хотите:
MATCH (tc:TBLCON)
WHERE $table IN tc.Tables
MATCH p=(tc)-[:Foo*]-()
WITH tc,
REDUCE(s = [], x IN COLLECT(NODES(p)) | s + x) AS ns,
REDUCE(t = [], y IN COLLECT(RELATIONSHIPS(p)) | t + y) AS rs
UNWIND ns AS n
WITH tc, rs, COLLECT(DISTINCT n) AS nodes
UNWIND rs AS rel
RETURN tc, nodes, COLLECT(DISTINCT rel) AS rels;
Предполагается, что вы предоставляете имя таблицы интереса (например, "TBL3") в качестве значения table
параметр. Это также предполагает, что все отношения интересов имеют Foo
тип.
Сначала находит tc
, TBLCON
узлы, содержащие это имя таблицы. Затем он использует ненаправленный поиск переменной длины для всех путей (с неповторяющимися связями), которые включают tc
, Затем он использует COLLECT
дважды: объединить список узлов в каждом пути и объединить список отношений в каждом пути. Каждый результат агрегации будет представлять собой список списков, поэтому он использует REDUCE
в каждом внешнем списке, чтобы объединить внутренние списки. Затем он использует UNWIND
а также COLLECT(DISTINCT x)
в каждом списке, чтобы создать список с уникальными элементами.
[ОБНОВИТЬ]
Если вы различаете ваши отношения по типу (а не по значению свойства), ваш Cypher-код может быть намного проще благодаря использованию функций APOC. В следующем запросе предполагается, что требуемые типы отношений передаются через types
параметр:
MATCH (tc:TBLCON)
WHERE $table IN tc.Tables
CALL apoc.path.subgraphAll(
tc, {relationshipFilter: apoc.text.join($types, '|')}) YIELD nodes, relationships
RETURN nodes, relationships;