APOC函数之路径(path)用法

本章来聊聊APOC里路径查询的用法,如果APOC库还不知道是什么或者不知道怎么安装可以参照文章APOC是啥了解了解!!!不要钱

文章中我们以查询产品光伏组件数据为例子。数据基于以下样本图:

返回结果MaterialsRelationship类型是一个关系实体,定义如下:

@Data@RelationshipEntity(type = "Materials")public class MaterialsRelationship {    @Id    private String uuid;    /**     * 开始节点     */    @StartNode    private ProductEntryNode startNode;    /**     * 结束节点     */    @EndNode    private ProductEntryNode endNode;}

比如要查询光伏组件上游关系类型包含Materials,Manufacture,Technology的路径,已知的是光伏组件的id,那么在dao层可以这么做

@Query(" match path=(p:ProductEntry)-[r:Materials|Manufacture|Technology*1..]->(pp)" +       " where p.productEntryId={productEntryId}" +       " return path")List<MaterialsRelationship> getProductEdgesList(String productEntryId);

这样就返回了光伏组件的上游所有路径和节点。用到了'*1..',表示查询的路径长度是无线大。很明显,这样使用在Neo4j里是不允许的。除非你能保证路径长度不超过6(官方推荐数字)。所以考虑把路径长度通过动态参数传入,像这样:

@Query(" match path=(p:ProductEntry)-[r:Materials|Manufacture|Technology*1..{level}]->(pp)" +       " where p.productEntryId={productEntryId}" +       " return path")List<MaterialsRelationship> getProductEdgesList(String productEntryId, int level);

很遗憾的是,cypher不支持这种传参。那怎么办呢?别着急,只要你能遇到的问题,Neo4j开发团队肯定已经遇到并且给出了解决方案。那就是封装成APOC函数了。具体怎么使用,一起来看看。找到apoc.path.expand的函数。这个函数就是查询节点的路径,具体使用语法看下:

apoc.path.expand(start :: ANY?, relationshipFilter :: STRING?, labelFilter :: STRING?, minLevel :: INTEGER?, maxLevel :: INTEGER?) :: (path :: PATH?)

参数说明:

  • start:开始节点,可以是任意类型;

  • relationshipFilter:关系类型,多个用|分开(STRING)

  • labelFilter:标签过滤(STRING)

  • minLevel:最小路径长度(INTEGER)

  • maxLevel:最大路径长度(INTEGER)

  • path:返回结果路径

  • 从参数里可以看出,maxLevel就是需要的传入参数。可以直接在dao层这样写了:

    @Query("match (p:ProductEntry) where p.productEntryId={productEntryId}" +       " call apoc.path.expand(p,'<Materials|<Manufacture|<Technology','+ProductEntry',1,{level}) yield path" +       " return path")List<MaterialsRelationship> getProductEdgesList(String productEntryId, int level);

    其中'<Materials|<Manufacture|<Technology'里的'<'表示指定的方向,如果查询是双向的可以不用加'<'。+ProductEntry表示上游关系只返回每个节点都有ProductEntry标签的路径。测试一下果然可以。说明路径长度可以通过APOC的函数apoc.path.expand动态传参的。返回结果类似这样:

    (p)-[r:Materials]->(pp:ProductEntry)-[r:Materials]->(ppp:ProductEntry)

    其他参数讲解一下。如果要查询下游数据,方向可以这样指定

    'Materials>|Manufacture>'或者没有方向'Materials|Manufacture':

    @Query("match (p:ProductEntry) where p.productEntryId={productEntryId}" +       " call apoc.path.expand(p,'Materials>|Manufacture>|Technology>','',1,{level}) yield path" +       " return path")List<MaterialsRelationship> getProductEdgesList(String productEntryId, int level);

    还可以使用标签过滤器指定遍历终止条件。如果想在遍历遇到包含Engineering标签的节点时立即终止遍历,这个是包含当前Engineering节点的,则可以使用/Engineering节点过滤器:

    @Query("match (p:ProductEntry) where p.productEntryId={productEntryId}" +       " call apoc.path.expand(p,'Materials>|Manufacture>|Technology>','/Engineering',1,{level}) yield path" +       " return path")List<MaterialsRelationship> getProductEdgesList(String productEntryId, int level);

    还可以使用'<Engineering'表示仅返回带有Engineering标签的节点处终止的路径,并且继续往下查找含有Engineering标签的节点,返回的结果类似这样:

    (p)-[r:Materials]->(pp:Engineering)-[r:Materials]->(ppp:Engineering)

    本篇讲的主要是apoc.path.expand函数的用法,包括解决了如何动态传参最大路径长度level,以及其他参数的说明。其中start还可以是id或者list,这些留给大家自己尝试。这里要说明我们不是为了用APOC而用,而是说在cypher中解决不了这样的问题,想到APOC函数有更好的解决方案。

    - 本期

    为方便看最新内容,记得关注Neo4j权威指南

    ©著作权归作者所有,转载或内容合作请联系作者
    平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

    推荐阅读更多精彩内容