neo4j - 在 Cypher 中获取具有特定类型的恰好一个关系的节点对,这些关系将它们相互连接
问题描述
我在 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 GB),因为收集操作会消耗太多内存。
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;
如何在不超过堆大小限制的情况下改进我的代码以获得所需的结果?
解决方案
这应该有效:
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
节点。
在度数检查之后,查询会执行一秒钟MATCH
以实际获取关联DrugDrugInteraction
节点。(我假设IS_PARTICIPANT_IN
关系只指向DrugDrugInteraction
节点,因此为了提高效率,从搜索模式中省略了标签)。
该RETURN
子句使用聚合函数 COLLECT
来收集Drug
每个名称的ddi
名称。(我假设ddi
节点具有唯一的名称。)
顺便说一句,如果有任意数量的Drug
s(不仅仅是 2 个)参与相同的 s DrugDrugInteraction
,并且没有其他的,这个查询也将起作用。此外,如果匹配项DrugDrugInteraction
碰巧有Drug
参与其他交互的相关项,则此查询不会将其包含Drug
在结果中(因为此查询仅关注d
通过初始度数检查的节点)。
推荐阅读
- sql - 将数据库内容克隆到现有数据库中
- itext - pdfStamper.AcroFields.SetField 不保留外观设置
- excel - 从 Outlook 宏自动打开后无法调用 Excel 宏
- javascript - 避免在 React 中由对象字面量引起的重新渲染:如何处理对象中的变量?
- php - CakePHP 3 - 分隔 JOIN 条件时使用不同的表别名
- jquery - 三消比赛
- google-chrome - 如何在 Chromebook 上使用 Assembla SVN 更新和提交?
- html - 更改 div 与背景图像之间的弹性间距
- c# - 来自 Azure 的 .net 核心流文件并调整大小
- bash - Bash PS1 提示设置 \h 在第一个点之后去除主机名