Получить пары узлов, имеющих ровно одно отношение определенного типа, которое связывает их друг с другом в Cypher - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть база данных графиков в Neo4j с информацией о наркотиках и взаимодействиях между наркотиками и другими. В связи с этим ()-[:IS_PARTICIPANT_IN]->() связывает лекарство с взаимодействием. Мне нужно получить те пары лекарств a и b, которые не участвуют ни в каких других отношениях :IS_PARTICIPANT_IN, кроме тех, которые между ними, то есть (a)-[:IS_PARTICIPANT_IN]->(ddi:DrugDrugInteraction)<-[:IS_PARTICIPANT_IN]-(b), без каких-либо других отношений IS_PARTICIPANT_IN, в которых нет ни a ни b.

Для этой цели я попытался выполнить следующий запрос Cypher. Однако в конечном итоге он достигает размера кучи (увеличивается до 8 ГБ), поскольку операции сбора занимают слишком много памяти.

MATCH (drug1:Drug)-[r1:IS_PARTICIPANT_IN]->(ddi:DrugDrugInteraction)
MATCH (drug2:Drug)-[r2:IS_PARTICIPANT_IN]->(ddi)
WHERE drug1 <> drug2 
OPTIONAL MATCH (drug2)-[r3:IS_PARTICIPANT_IN]->(furtherDDI:DrugDrugInteraction)
WHERE furtherDDI <> ddi
WITH drug1, drug2, ddi, COLLECT(ddi) AS ddis, furtherDDI, COLLECT(furtherDDI) AS additionalDDIs
WITH drug1, drug2, ddi, COUNT(ddis) AS n1, COUNT(additionalDDIs) AS n2
WHERE n1 = 1 AND n2 = 0
RETURN drug1.name, drug2.name, ddi.name ORDER BY drug1;

Как улучшить код, чтобы получить желаемые результаты, не превышая размер кучи предел?

1 Ответ

2 голосов
/ 25 февраля 2020

Это должно работать:

MATCH (d:Drug)
WHERE SIZE((d)-[:IS_PARTICIPANT_IN]->()) = 1
MATCH (d)-[:IS_PARTICIPANT_IN]->(ddi)
RETURN ddi.name AS ddiName, COLLECT(d.name) AS drugNames
ORDER BY drugNames[0]

Предложение WHERE использует очень эффективную проверку степени защиты для фильтрации Drug узлов, которые имеют только одну исходящую IS_PARTICIPANT_IN связь. Эта проверка эффективна, потому что на самом деле ей не нужно получать какие-либо DrugDrugInteraction узлы.

После проверки degreeness запрос выполняет второй MATCH, чтобы фактически получить связанный узел DrugDrugInteraction. (Я предполагаю, что отношение IS_PARTICIPANT_IN указывает только на узлы DrugDrugInteraction и поэтому для эффективности исключило метку из шаблона поиска).

В предложении RETURN используется функция агрегирования COLLECT для сбора Drug имен для каждого ddi имени. (Я предполагаю, что ddi узлы имеют уникальные имена.)

Кстати, этот запрос также будет работать, если есть любое количество Drug с (не только 2), которые участвуют в том же DrugDrugInteraction и никаких других. Кроме того, если у совпадающего DrugDrugInteraction есть связанный Drug, который участвует в других взаимодействиях, этот запрос не будет включать этот Drug в результат (так как этот запрос обращает внимание только на d узлов, которые прошли начальный проверка степени экологичности).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...