【问题标题】:Restructuring a large cypher union query重构大型密码联合查询
【发布时间】:2019-04-08 23:54:23
【问题描述】:

我有一个很长的密码查询,它使用联合,但是,有一些常见的语句(粗体)在两个查询中重复。有没有办法我可以分解,甚至存储公共语句的结果集,然后在稍后将它们分支和合并?我已经调查过使用 with、collect 和 optional match 但无济于事。

MATCH (s:Subject), (p:Programme)
在 ['A', 'B', 'C'] 中的 s.name
将收集作为 subs, p
WITH p, subs, SIZE(FILTER(c in subs WHERE c.level ="CSEC")) 作为 csecs, SIZE(FILTER(c in subs WHERE c. level ="CAPE")) 作为披风
WHERE p.csec_passes MATCH (p:Programme)-[:requires]->(s:Subject)

WITH p, subs, COLLECT(s) AS mandatories WHERE ALL(n IN mandatories WHERE n IN subs) 而不是 (p)-->(:Combo)
返回 p

联合

MATCH (s:Subject), (p:Programme)
在 ['A', 'B', 'C'] 中的 s.name
将收集作为 subs, p
WITH p, subs, SIZE(FILTER(c in subs WHERE c.level ="CSEC")) 作为 csecs, SIZE(FILTER(c in subs WHERE c. level ="CAPE")) 作为披风
WHERE p.csec_passes MATCH (p:Programme)-[:requires]->(s:Subject)

WITH p, subs, COLLECT(s) AS 强制要求 WHERE ALL(n IN 强制要求 WHERE n IN subs)
MATCH (p)-[:requires]->(c:Combo)-[:contains]->(s:Subject)
将 p、c、subs、collect(s) 作为列表
WITH p, subs, collect({amt:c.amt, set:list}) 作为组合
WHERE ALL(combo in combo.amt

一些额外的上下文;所有程序节点都连接到至少一个称为强制的主题节点。此外,一些程序节点还连接到一个或多个组合节点。在这种情况下,需要对程序进行更多检查,我将联合查询组合和非组合两种类型。

【问题讨论】:

    标签: neo4j cypher query-optimization graph-databases


    【解决方案1】:

    首先,有几个重要说明。

    1. Cypher 并未规定如何检索信息。这种优化是 Cypher 规划器应该处理的(现在不需要,但将来可能会改变)

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


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

    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
    

    【讨论】:

    • 谢谢,经过一些测试,我发现它更快地产生相同的结果。你介意我把这个查询放在网站上吗?
    • @Snickdx 随意,这就是分享按钮的用途。 :3
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多