Neo4j 重组大型密码联合查询

Neo4j 重组大型密码联合查询,neo4j,cypher,query-optimization,graph-databases,Neo4j,Cypher,Query Optimization,Graph Databases,我有一个非常长的使用union的cypher查询,但是,在两个查询中都重复了一些常用语句(粗体)。有没有一种方法可以将公共语句的结果集分解出来,甚至存储起来,然后在以后对它们进行分支和联合?我已经调查了使用with、collect和可选匹配,但没有结果 匹配(s:Subject),(p:program)其中s.name在['A','B','C'] 以collect(s)作为subs,p以p,subs,SIZE(FILTER(c in subs,其中c.level=“CSEC”))作为CSEC,S

我有一个非常长的使用union的cypher查询,但是,在两个查询中都重复了一些常用语句(粗体)。有没有一种方法可以将公共语句的结果集分解出来,甚至存储起来,然后在以后对它们进行分支和联合?我已经调查了使用with、collect和可选匹配,但没有结果

匹配(s:Subject),(p:program)
其中s.name在['A','B','C']
以collect(s)作为subs,p
以p,subs,SIZE(FILTER(c in subs,其中c.level=“CSEC”))作为CSEC,SIZE(FILTER(c in subs,其中c.level=“CAPE”))作为CAPE
其中p.csec_通过(:Combo)
返回p

联合

匹配(s:Subject),(p:program)
其中s.name在['A','B','C']
以collect(s)作为subs,p
以p,subs,SIZE(FILTER(c in subs,其中c.level=“CSEC”))作为CSEC,SIZE(FILTER(c in subs,其中c.level=“CAPE”))作为CAPE
其中p.csec_通过(c:Combo)-[:包含]->(s:Subject)
将p、c、Sub、collect作为列表
使用p,subs,collect({amt:c.amt,set:list})作为组合

WHERE ALL(combo in combos WHERE combo.amt首先是几个重要的注释

  • Cypher不规定如何检索信息。这种优化是Cypher planner应该处理的事情(现在没有,但将来可能会改变)

  • Cypher并行运行UNION查询,这意味着除非您将Neo4j服务器推到其极限,否则查询的时间应该与您只运行两个查询中较昂贵的查询的时间几乎没有区别。(请注意,由于内存缓存的原因,重复运行可能会更快)因此,如果时间是你的问题,它就不应该是。如果DBHits是问题,那么现在你就不应该使用UNION


  • 也就是说,我可以通过添加
    OPTIONAL
    SIZE(combo.set)=0或
    来组合这两个查询。添加注释以解释逻辑

    MATCH (s:Subject), (p:Programme) 
    WHERE s.name in ['A', 'B', 'C'] 
    WITH collect(s) as subs, p 
    WITH p, subs, SIZE(FILTER(c in subs WHERE c.level ="CSEC")) as csecs, SIZE(FILTER(c in subs WHERE c.level ="CAPE")) as capes 
    WHERE p.csec_passes <= csecs AND p.cape_passes <= capes 
    MATCH (p:Programme)-[:requires]->(s:Subject)
    
    WITH p, subs, COLLECT(s) AS mandatories WHERE ALL(n IN mandatories WHERE n IN subs)
    OPTIONAL MATCH (p)-[:requires]->(c:Combo)-[:contains]->(s:Subject)
    // Where c is null, list is empty
    WITH p, c, subs, collect(s) as list
    // If c is null, combos is a list of empty lists
    WITH p, subs, collect({amt:c.amt, set:list}) as combos
    // SIZE(combo.set)=0 is true if the list is null or an empty list
    WHERE ALL(combo in combos where SIZE(combo.set)=0 OR combo.amt <= size(apoc.coll.intersection(subs, combo.set))) RETURN p
    
    匹配(s:主题),(p:程序)
    其中s.name在['A','B','C']
    将collect(s)作为subs,p
    将p、subs、SIZE(过滤器(c在subs中,其中c.level=“CSEC”))作为CSEC,SIZE(过滤器(c在subs中,其中c.level=“CAPE”))作为CAPE
    其中p.csec_通过(c:Combo)-[:包含]->(s:Subject)
    //其中c为null,list为空
    以p、c、subs、collect(s)作为列表
    //如果c为null,则combos是一个空列表列表
    使用p,subs,collect({amt:c.amt,set:list})作为组合
    //如果列表为空或为空,则SIZE(combo.set)=0为真
    
    WHERE ALL(combo in combos WHERE SIZE(combo.set)=0或combo.amt谢谢,经过一点测试,我发现它可以更快地生成相同的结果。您介意我定位此查询吗?@Snickdx请随意,这就是共享按钮的作用。:3