我在Neo4j中有这个元图:
:Protein ---> :is_a ---------------> :Enzyme ---> :activated_by|inhibited_by ---> :Compound
\<-- :activated_by <---/
:Compound --> :consumed_by|:produced_by ---> :Transport
\<---- :catalyzed_by -------<---/
:Transport --> part_of ---> :Pathway
(是的,它是生物学,是的,它是从BioPAX导入的) .
我想使用Cypher返回通过某个图形路径链接的所有 (:Protein, :Compounds)
对 . 虽然一种简单的方法是遵循两种节点类型之间的每条可能路径并对每种节点类型发出一个查询,但显然使用某种模式联合的查询会更紧凑(可能更慢,我正在评估不同方法的性能) .
但是如何编写这样的查询呢?我已经读过Cypher有一个UNION结构,但我还不清楚如何组合和嵌套它们,例如,关于从酶到传输的子图,我希望能够写出与这个非正式表达式相当的东西:
enz:Enzyme :activated|inhibited_by comp:Compund
join with: (
(comp :consumed_by|produced_by :Transport)
UNION (:Transport :catalyzed_by comp )
)
我读过there should be some way,但是我没有试图理解是否有一种相对简单的方法(在SPARQL或SQL中,上面的内容相当简单) .
3 回答
使用定期收集
在Cypher中,您可以使用WITH将查询分解为步骤,并且可以通过将它们连接在一起来连接两个列表 .
使用Union
当使用Union来组合不同的查询时,可以将它想象成逗号分隔的查询列表,而不是逗号,而是使用单词UNION(此外,此列表中的每个查询都必须具有相同的返回列 .
这对于组合完全不同的查询的结果很有用,但由于您组合的查询通常是相关的,因此大多数时候COLLECT将更有效,并且可以更好地控制结果 .
使用OR
您可以使用TYPE函数获取关系的名称并对其进行过滤 .
注意:对于仅在它们的关系类型上使用OR,您也可以使用
-[:A|:B]->
进行OR .使用路径过滤
从Neo4j 3.1.x开始,Cypher相当擅长自由寻路 . (通过这种方式,我的意思是找到一个有效的路径而不搜索所有可能的路径._783306的模式)上限不是严格必要的,但对于防止/控制失控查询很有用 .
其他
如果他们的关系类型实际上并不重要,你可以只使用
(e:Enzyme)-->(c:Compound)
或忽略方向(e:Enzyme)--(c:Compound)
如果是一个选项,我建议重构您的模式以使其更加一致(或添加与此匹配条件相关的关系类型),这样您就不需要联合结果 . (这将为您提供最佳性能,因为Cypher规划人员将更好地了解如何快速找到您的结果)
下面的查询将返回
Enzyme
被Transport
消耗,生成或催化的Compound
激活或禁止的所有路径 .查询的
r2
关系模式是非方向性的,因为catalyzed_by
的方向性与consumed_by
和produced_by
的方向性相反 .所以,我还没有找到一个令人满意的方式来做我最初的要求,但我非常接近它,我想报告一下 .
首先,我的初始图形与我实际的图形略有不同,因此我将基于真实图形的下一个示例(抱歉混淆):
我可以使用WHERE子句中的路径非常舒适地工作(加上,在更简单的情况下,UNIONS):
// Branch 2 MATCH (prot:Protein), (enz:Enzyme), (tns:Transport) - [:part_of] -> (path:Path) WHERE ( (enz) - [:ac_by|:in_by] -> (:Comp) - [:pd_by|:cs_by] -> (tns) // Branch 2.1 OR (tns) - [:ca_by] -> (enz) ) //Branch 2.2 (pt1) AND ( (prot) - [:is_a] -> (enz) OR (prot) <- [:ac_by] - (enz) ) // Branch 2.2 (pt2) RETURN prot, path LIMIT 30 UNION // Branch1 MATCH (prot:Protein) - [:pd_by|:cs_by] -> (:Reaction) - [:part_of] -> (path:Path) RETURN prot, path LIMIT 30
(我也很抱歉所有这些缩写,例如,pd_by是produ_by,ac_by是activate_by等等) .
该查询在大约1分钟内产生结果 . 太长了,这显然是由于查询的解释方式,正如人们从其计划中可以看到的那样:
我真的不明白为什么会有那些巨大的笛卡尔产品 . 我尝试过WITH / UNWIND方法,但是我无法得到正确的结果(请参阅上面的评论,感谢@Tezra和@cybersam),即使我是,也是一个非常困难的语法 .