CYPHER解构之图模型映射到图数据模型

 

Here’s the table of contents:

  1. 图模型CYPHER
  2. 图数据模型CYPHER
  3. 指定节点的唯一属性生成指定ID的虚拟节点数据
  4. 图数据模型CYPHER-统一节点ID使用GRAPH返回【非单条路径】

图模型CYPHER

MATCH p=(com0:公司)<-[:担保]-(com1:公司)<-[:持股]-(com2:公司)-[:持股]->(com3:公司)-[:属于]->(idus:行业)  WHERE idus.name='轻工' RETURN p LIMIT 25

图数据模型CYPHER

  • 按WHERE条件拆分SCHEMA为多个子图
    // 行业
    MATCH (startNode:行业 {name:'轻工'}) WITH startNode
    CALL apoc.path.subgraphNodes(startNode, {maxLevel:2, relationshipFilter:'NEXT>', labelFilter:'行业', bfs:true, filterStartNode:false, limit:-1}) YIELD node WITH COLLECT(node.name) AS idusList
    // com3所属的行业 com3->tmpCom3
    MATCH (tmpCom3:UDCompany)-[:拥有]->(:UDBrand)<-[:包含]-(:UDProduct)-[:BELONG_TO]->(idus:UDIndustry) WHERE idus.name IN idusList WITH tmpCom3,idus
    // com3链接 com3<-tmpCom3
    MATCH (tmpCom2:HORGShareHoldV002)<-[:持股]-(com3:HORGShareHoldV002) WHERE com3.hcode=tmpCom3.hcode WITH tmpCom2,tmpCom3,idus
    // com2链接
    MATCH (tmpCom1:HORGShareHoldV002)<-[:持股]-(com2:HORGShareHoldV002) WHERE com2.hcode=tmpCom2.hcode WITH tmpCom1,tmpCom2,tmpCom3,idus
    // com1链接
    //MATCH (com0:HORGGuaranteeV003)<-[:担保]-(com1:HORGGuaranteeV003) WHERE com1.hcode=tmpCom1.hcode WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    MATCH (com0)-[]->(com1:PRE公司中文名称) WHERE com1.name=tmpCom1.name WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    // 拼接结果返回
    RETURN com0.name,tmpCom1.name,tmpCom2.name,tmpCom3.name,idus.name LIMIT 25
    
    // 行业
    MATCH (startNode:行业 {name:'轻工'}) WITH startNode
    CALL apoc.path.subgraphNodes(startNode, {maxLevel:2, relationshipFilter:'NEXT>', labelFilter:'行业', bfs:true, filterStartNode:false, limit:-1}) YIELD node WITH COLLECT(node.name) AS idusList
    // com3所属的行业 com3->tmpCom3
    MATCH p1=(tmpCom3:UDCompany)-[:拥有]->(:UDBrand)<-[:包含]-(:UDProduct)-[:BELONG_TO]->(idus:UDIndustry) WHERE idus.name IN idusList WITH tmpCom3,idus,p1
    // com3链接 com3<-tmpCom3
    MATCH p2=(tmpCom2:HORGShareHoldV002)<-[:持股]-(com3:HORGShareHoldV002) WHERE com3.hcode=tmpCom3.hcode WITH tmpCom2,tmpCom3,idus,p2,p1
    // com2链接
    MATCH p3=(tmpCom1:HORGShareHoldV002)<-[:持股]-(com2:HORGShareHoldV002) WHERE com2.hcode=tmpCom2.hcode WITH tmpCom1,tmpCom2,tmpCom3,idus,p3,p2,p1
    // com1链接
    //MATCH (com0:HORGGuaranteeV003)<-[:担保]-(com1:HORGGuaranteeV003) WHERE com1.hcode=tmpCom1.hcode WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    MATCH p4=(com0)-[]->(com1:PRE公司中文名称) WHERE com1.name=tmpCom1.name WITH com0,tmpCom1,tmpCom2,tmpCom3,idus,p3,p2,p1
    // 拼接结果返回
    RETURN com0.name,tmpCom1.name,tmpCom2.name,tmpCom3.name,idus.name LIMIT 25
    
  • 使用虚拟节点和虚拟关系存储过程聚合数据
    // ==========子图拆分==========
    // ==========子图拆分-行业树子图聚合==========
    // 行业
    MATCH (startNode:行业 {name:'轻工'}) WITH startNode
    CALL apoc.path.subgraphNodes(startNode, {maxLevel:2, relationshipFilter:'NEXT>', labelFilter:'行业', bfs:true, filterStartNode:false, limit:-1}) YIELD node WITH COLLECT(node.name) AS idusList
    // ==========子图拆分-UIDS子图==========
    // com3所属的行业 com3->tmpCom3
    MATCH (tmpCom3:UDCompany)-[:拥有]->(:UDBrand)<-[:包含]-(:UDProduct)-[:BELONG_TO]->(idus:UDIndustry) WHERE idus.name IN idusList WITH tmpCom3,idus
    // ==========子图拆分-持股网络==========
    // com3链接 com3<-tmpCom3
    MATCH (tmpCom2:HORGShareHoldV002)<-[:持股]-(com3:HORGShareHoldV002) WHERE com3.hcode=tmpCom3.hcode WITH tmpCom2,tmpCom3,idus
    // com2链接
    MATCH (tmpCom1:HORGShareHoldV002)<-[:持股]-(com2:HORGShareHoldV002) WHERE com2.hcode=tmpCom2.hcode WITH tmpCom1,tmpCom2,tmpCom3,idus
    // ==========子图拆分-担保网络==========
    // com1链接
    //MATCH (com0:HORGGuaranteeV003)<-[:担保]-(com1:HORGGuaranteeV003) WHERE com1.hcode=tmpCom1.hcode WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    MATCH (com0)-[]->(com1:PRE公司中文名称) WHERE com1.name=tmpCom1.name WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    // ==========结果集聚合==========
    // 拼接结果返回
    //RETURN com0.name,tmpCom1.name,tmpCom2.name,tmpCom3.name,idus.name LIMIT 25
    // 创建虚拟节点
    CALL apoc.create.vNode(['公司'],{hcode:com0.name,name:com0.name}) YIELD node WITH node AS nCom0,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL apoc.create.vNode(['公司'],{hcode:tmpCom1.hcode,name:tmpCom1.name}) YIELD node WITH node AS nTmpCom1,nCom0,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL apoc.create.vNode(['公司'],{hcode:tmpCom2.hcode,name:tmpCom2.name}) YIELD node WITH node AS nTmpCom2,nTmpCom1,nCom0,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL apoc.create.vNode(['公司'],{hcode:tmpCom3.hcode,name:tmpCom3.name}) YIELD node WITH node AS nTmpCom3,nTmpCom2,nTmpCom1,nCom0,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL apoc.create.vNode(['行业'],{hcode:idus.hcode,name:idus.name}) YIELD node WITH node AS nIdus,nTmpCom3,nTmpCom2,nTmpCom1,nCom0,com0,tmpCom1,tmpCom2,tmpCom3,idus
    // 创建虚拟关系
    CALL apoc.create.vRelationship(nTmpCom1,'担保',{},nCom0) YIELD rel WITH rel AS nTmpCom1com0rel,nIdus,nTmpCom3,nTmpCom2,nTmpCom1,nCom0
    CALL apoc.create.vRelationship(nTmpCom2,'持股',{},nTmpCom1) YIELD rel WITH nTmpCom1com0rel,rel AS nTmpCom2nTmpCom1rel,nIdus,nTmpCom3,nTmpCom2,nTmpCom1,nCom0
    CALL apoc.create.vRelationship(nTmpCom2,'持股',{},nTmpCom3) YIELD rel WITH nTmpCom1com0rel,nTmpCom2nTmpCom1rel,rel AS nTmpCom2nTmpCom3rel,nIdus,nTmpCom3,nTmpCom2,nTmpCom1,nCom0
    CALL apoc.create.vRelationship(nTmpCom3,'属于',{},nIdus) YIELD rel WITH nTmpCom1com0rel,nTmpCom2nTmpCom1rel,nTmpCom2nTmpCom3rel,rel AS nTmpCom3nIdusrel,nIdus,nTmpCom3,nTmpCom2,nTmpCom1,nCom0
    // 拼接路径
    WITH (nCom0)<-[nTmpCom1com0rel]-(nTmpCom1)<-[nTmpCom2nTmpCom1rel]-(nTmpCom2)-[nTmpCom2nTmpCom3rel]->(nTmpCom3)-[nTmpCom3nIdusrel]->(nIdus) AS path
    RETURN path LIMIT 25
    
  • 使用vPatternFull聚合虚拟图数据
    图数据模型CYPHER:
    // ==========子图拆分==========
    // ==========子图拆分-行业树子图聚合==========
    // 行业
    MATCH (startNode:行业 {name:'轻工'}) WITH startNode
    CALL apoc.path.subgraphNodes(startNode, {maxLevel:2, relationshipFilter:'NEXT>', labelFilter:'行业', bfs:true, filterStartNode:false, limit:-1}) YIELD node WITH COLLECT(node.name) AS idusList
    // ==========子图拆分-UIDS子图==========
    // com3所属的行业 com3->tmpCom3
    MATCH (tmpCom3:UDCompany)-[:拥有]->(:UDBrand)<-[:包含]-(:UDProduct)-[:BELONG_TO]->(idus:UDIndustry) WHERE idus.name IN idusList WITH tmpCom3,idus
    // ==========子图拆分-持股网络==========
    // com3链接 com3<-tmpCom3
    MATCH (tmpCom2:HORGShareHoldV002)<-[:持股]-(com3:HORGShareHoldV002) WHERE com3.hcode=tmpCom3.hcode WITH tmpCom2,tmpCom3,idus
    // com2链接
    MATCH (tmpCom1:HORGShareHoldV002)<-[:持股]-(com2:HORGShareHoldV002) WHERE com2.hcode=tmpCom2.hcode WITH tmpCom1,tmpCom2,tmpCom3,idus
    // ==========子图拆分-担保网络==========
    // com1链接
    //MATCH (com0:HORGGuaranteeV003)<-[:担保]-(com1:HORGGuaranteeV003) WHERE com1.hcode=tmpCom1.hcode WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    MATCH (com0)-[]->(com1:PRE公司中文名称) WHERE com1.name=tmpCom1.name WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    // ==========结果集聚合==========
    // 拼接结果返回
    //RETURN com0.name,tmpCom1.name,tmpCom2.name,tmpCom3.name,idus.name LIMIT 25
    // 创建虚拟关系和节点-拼接路径
    CALL apoc.create.vPatternFull(['公司'],{name:tmpCom1.name},'担保',{},['公司'],{name:com0.name}) YIELD from,rel,to WITH (from)-[rel]-(to) AS path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL apoc.create.vPatternFull(['公司'],{name:tmpCom2.name},'持股',{},['公司'],{name:tmpCom1.name}) YIELD from,rel,to WITH (from)-[rel]-(to) AS path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL apoc.create.vPatternFull(['公司'],{name:tmpCom2.name},'持股',{},['公司'],{name:tmpCom3.name}) YIELD from,rel,to WITH (from)-[rel]-(to) AS path3,path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL apoc.create.vPatternFull(['公司'],{name:tmpCom3.name},'属于',{},['行业'],{name:idus.name}) YIELD from,rel,to WITH (from)-[rel]-(to) AS path4,path3,path2,path1
    RETURN * LIMIT 25
    

指定节点的唯一属性生成指定ID的虚拟节点数据

  • 指定ID生成虚拟节点【指定节点ID】
    //CALL apoc.create.vNode(['Person'],{name:'John'}) YIELD node RETURN node
    CALL olab.create.vNode(['行业'],{hcode:'HINDUS',name:'轻工'},-109) YIELD node RETURN node
    RETURN olab.create.vNode(['行业'],-109,{hcode:'HINDUS',name:'轻工'}) AS node
    
  • 指定节点ID生成虚拟PATH【指定节点ID】【默认关系生成原子性ID】【支持指定关系ID】
    //CALL apoc.create.vPatternFull(['Person'],{name:'John'},'KNOWS',{since:2010},['Person'],{name:'Jane'}) YIELD from,rel,to RETURN from,rel,to
    CALL olab.create.vPatternFull(['Person'],{name:'John'},-109,'KNOWS',{since:2010},-1,['Person'],{name:'Jane'},-110) YIELD from,rel,to WITH (from)-[rel]->(to) AS path RETURN path
    UNION
    CALL olab.create.vPatternFull(['Person'],{name:'John'},-109,'KNOWS',{since:2010},-2,['Person'],{name:'Jane'},-111) YIELD from,rel,to WITH (from)-[rel]->(to) AS path RETURN path
    
    CALL olab.create.vPatternFull(['Person'],{name:'John'},-109,'KNOWS',{since:2010},-3,['Person'],{name:'Jane'},-111) YIELD from,rel,to WITH (from)-[rel]->(to) AS path RETURN path
    

图数据模型CYPHER-统一节点ID使用GRAPH返回【非单条路径】

  • 使用vPatternFull聚合虚拟图数据【同类型关系会重复】
    图数据模型CYPHER:
    // ==========子图拆分==========
    // ==========子图拆分-行业树子图聚合==========
    // 行业
    MATCH (startNode:行业 {name:'轻工'}) WITH startNode
    CALL apoc.path.subgraphNodes(startNode, {maxLevel:2, relationshipFilter:'NEXT>', labelFilter:'行业', bfs:true, filterStartNode:false, limit:-1}) YIELD node WITH COLLECT(node.name) AS idusList
    // ==========子图拆分-UIDS子图==========
    // com3所属的行业 com3->tmpCom3
    MATCH (tmpCom3:UDCompany)-[:拥有]->(:UDBrand)<-[:包含]-(:UDProduct)-[:BELONG_TO]->(idus:UDIndustry) WHERE idus.name IN idusList WITH tmpCom3,idus
    // ==========子图拆分-持股网络==========
    // com3链接 com3<-tmpCom3
    MATCH (tmpCom2:HORGShareHoldV002)<-[:持股]-(com3:HORGShareHoldV002) WHERE com3.hcode=tmpCom3.hcode WITH tmpCom2,tmpCom3,idus
    // com2链接
    MATCH (tmpCom1:HORGShareHoldV002)<-[:持股]-(com2:HORGShareHoldV002) WHERE com2.hcode=tmpCom2.hcode WITH tmpCom1,tmpCom2,tmpCom3,idus
    // ==========子图拆分-担保网络==========
    // com1链接
    //MATCH (com0:HORGGuaranteeV003)<-[:担保]-(com1:HORGGuaranteeV003) WHERE com1.hcode=tmpCom1.hcode WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    MATCH (com0)-[]->(com1:PRE公司中文名称) WHERE com1.name=tmpCom1.name WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    // ==========结果集聚合==========
    // 拼接结果返回
    //RETURN com0.name,tmpCom1.name,tmpCom2.name,tmpCom3.name,idus.name LIMIT 25
    // 创建虚拟关系和节点-拼接路径【节点使用负数ID】【关系使用系统生成的原子性ID】
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom1.name},-ID(tmpCom1),'担保',{},null,['公司'],{name:com0.name},-ID(com0)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom2.name},-ID(tmpCom2),'持股',{},null,['公司'],{name:tmpCom1.name},-ID(tmpCom1)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom2.name},-ID(tmpCom2),'持股',{},null,['公司'],{name:tmpCom3.name},-ID(tmpCom3)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path3,path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom3.name},-ID(tmpCom3),'属于',{},null,['行业'],{name:idus.name},-ID(idus)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path4,path3,path2,path1
    RETURN * LIMIT 25
    
  • 使用vPatternFull聚合虚拟图数据【同类型关系不会重复】
    图数据模型CYPHER:
    // ==========子图拆分==========
    // ==========子图拆分-行业树子图聚合==========
    // 行业
    MATCH (startNode:行业 {name:'轻工'}) WITH startNode
    CALL apoc.path.subgraphNodes(startNode, {maxLevel:2, relationshipFilter:'NEXT>', labelFilter:'行业', bfs:true, filterStartNode:false, limit:-1}) YIELD node WITH COLLECT(node.name) AS idusList
    // ==========子图拆分-UIDS子图==========
    // com3所属的行业 com3->tmpCom3
    MATCH (tmpCom3:UDCompany)-[:拥有]->(:UDBrand)<-[:包含]-(:UDProduct)-[:BELONG_TO]->(idus:UDIndustry) WHERE idus.name IN idusList WITH tmpCom3,idus
    // ==========子图拆分-持股网络==========
    // com3链接 com3<-tmpCom3
    MATCH (tmpCom2:HORGShareHoldV002)<-[:持股]-(com3:HORGShareHoldV002) WHERE com3.hcode=tmpCom3.hcode WITH tmpCom2,tmpCom3,idus
    // com2链接
    MATCH (tmpCom1:HORGShareHoldV002)<-[:持股]-(com2:HORGShareHoldV002) WHERE com2.hcode=tmpCom2.hcode WITH tmpCom1,tmpCom2,tmpCom3,idus
    // ==========子图拆分-担保网络==========
    // com1链接
    //MATCH (com0:HORGGuaranteeV003)<-[:担保]-(com1:HORGGuaranteeV003) WHERE com1.hcode=tmpCom1.hcode WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    MATCH (com0)-[]->(com1:PRE公司中文名称) WHERE com1.name=tmpCom1.name WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    // ==========结果集聚合==========
    // 拼接结果返回
    //RETURN com0.name,tmpCom1.name,tmpCom2.name,tmpCom3.name,idus.name LIMIT 25
    // 创建虚拟关系和节点-拼接路径【节点使用负数ID】【关系使用系统生成的原子性ID】
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom1.name},-ID(tmpCom1),'担保',{},null,['公司'],{name:com0.name},-ID(com0)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom2.name},-ID(tmpCom2),'持股',{},null,['公司'],{name:tmpCom1.name},-ID(tmpCom1)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom2.name},-ID(tmpCom2),'持股',{},null,['公司'],{name:tmpCom3.name},-ID(tmpCom3)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path3,path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom3.name},-ID(tmpCom3),'属于',{},null,['行业'],{name:idus.name},-ID(idus)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path4,path3,path2,path1
    RETURN * LIMIT 25
    
  • 全局唯一ID表【使用MySQL实现】【根据查询性能考虑是否使用ES】【数据量可能会在千百亿】
    核心字段:
    自增ID,限制字段
    
    // 节点ID表
    输入:节点ID
    返回:返回一个自增ID【虚拟图需要的自增ID】
    数据存储在MySQL-ONGDB_UNIQUE_WITH_AUTO_NODE_ID
    数据写入逻辑:存在更新,不存在则新增
    函数:RETURN custom.auto.node.id('HORG20f2833a17034a812349e1933d9c5e5f') AS nodeVAutoId
    
    // 关系ID表
    输入:主节点ID,关系类型,从节点ID
    返回:返回一个自增ID
    数据存储在MySQL-ONGDB_UNIQUE_WITH_AUTO_REL_ID
    数据写入逻辑:存在更新,不存在则新增
    函数:RETURN custom.auto.rel.id('HORG20f2833a17034a812349e1933d9c5e5f','担保','HORGa334e4057b12f53499c93d483c426993') AS relVAutoId
    
  • 实体全域唯一ID系统实现虚拟图的生成
  • 【设计LONG类型唯一代码】【用来合并聚合结果】【ID维护在MYSQL或者ES集群】【所有有唯一性限制的实体都需要维护一个LONG类型ID】【查询运行时动态从MySQL或ES获取】
    图数据模型CYPHER:
    // ==========子图拆分==========
    // ==========子图拆分-行业树子图聚合==========
    // 行业
    MATCH (startNode:行业 {name:'轻工'}) WITH startNode
    CALL apoc.path.subgraphNodes(startNode, {maxLevel:2, relationshipFilter:'NEXT>', labelFilter:'行业', bfs:true, filterStartNode:false, limit:-1}) YIELD node WITH COLLECT(node.name) AS idusList
    // ==========子图拆分-UIDS子图==========
    // com3所属的行业 com3->tmpCom3
    MATCH (tmpCom3:UDCompany)-[:拥有]->(:UDBrand)<-[:包含]-(:UDProduct)-[:BELONG_TO]->(idus:UDIndustry) WHERE idus.name IN idusList WITH tmpCom3,idus
    // ==========子图拆分-持股网络==========
    // com3链接 com3<-tmpCom3
    MATCH (tmpCom2:HORGShareHoldV002)<-[:持股]-(com3:HORGShareHoldV002) WHERE com3.hcode=tmpCom3.hcode WITH tmpCom2,tmpCom3,idus
    // com2链接
    MATCH (tmpCom1:HORGShareHoldV002)<-[:持股]-(com2:HORGShareHoldV002) WHERE com2.hcode=tmpCom2.hcode WITH tmpCom1,tmpCom2,tmpCom3,idus
    // ==========子图拆分-担保网络==========
    // com1链接
    //MATCH (com0:HORGGuaranteeV003)<-[:担保]-(com1:HORGGuaranteeV003) WHERE com1.hcode=tmpCom1.hcode WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    MATCH (com0)-[]->(com1:PRE公司中文名称) WHERE com1.name=tmpCom1.name WITH com0,tmpCom1,tmpCom2,tmpCom3,idus
    // ==========结果集聚合==========
    // 拼接结果返回
    //RETURN com0.name,tmpCom1.name,tmpCom2.name,tmpCom3.name,idus.name LIMIT 25
    // 创建虚拟关系和节点-拼接路径【节点使用负数ID】【关系使用系统生成的原子性ID】
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom1.name},-custom.auto.node.id(tmpCom1.hcode),'担保',{},custom.auto.rel.id(tmpCom1.hcode,'担保',com0.name),['公司'],{name:com0.name},-custom.auto.node.id(com0.name)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom2.name},-custom.auto.node.id(tmpCom2.hcode),'持股',{},custom.auto.rel.id(tmpCom2.hcode,'持股',tmpCom1.hcode),['公司'],{name:tmpCom1.name},-custom.auto.node.id(tmpCom1.hcode)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom2.name},-custom.auto.node.id(tmpCom2.hcode),'持股',{},custom.auto.rel.id(tmpCom2.hcode,'持股',tmpCom3.hcode),['公司'],{name:tmpCom3.name},-custom.auto.node.id(tmpCom3.hcode)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path3,path2,path1,com0,tmpCom1,tmpCom2,tmpCom3,idus
    CALL olab.create.vPatternFull(['公司'],{name:tmpCom3.name},-custom.auto.node.id(tmpCom3.hcode),'属于',{},custom.auto.rel.id(tmpCom3.hcode,'属于',idus.hcode),['行业'],{name:idus.name},-custom.auto.node.id(idus.hcode)) YIELD from,rel,to WITH (from)-[rel]-(to) AS path4,path3,path2,path1
    RETURN [path1[0],path2[0],path3[0],path4[0]] AS path LIMIT 25