neo4j - 重构大型密码联合查询

标签 neo4j cypher query-optimization graph-databases

我有一个非常长的密码查询,它使用联合,但是,有一些常见的语句(以粗体显示)在两个查询中重复。有没有一种方法可以分解,甚至存储公共(public)语句的结果集,然后在以后对它们进行分支和联合?我研究过使用 with、collect 和可选匹配,但没有结果。

MATCH (s:主题), (p:程序)
WHERE s.name in ['A', 'B', 'C']
使用collect(s)作为subs,p
使用p,subs,SIZE(FILTER(c in subs WHERE c.level ="CSEC")) as csecs,SIZE(FILTER(c in subs WHERE) c.level ="CAPE")) 作为斗篷 其中 p.csec_passes <= csecs AND p.cape_passes <= capes
MATCH (p:程序)-[:需要]->(s:主题)

将 p、subs、COLLECT(s) 作为强制项,其中所有(n 在强制项中,其中 n 在 subs 中)AND NOT (p)-->(:Combo)
返回页

联盟

MATCH (s:主题), (p:程序)
WHERE s.name in ['A', 'B', 'C']
使用collect(s)作为subs,p
使用p,subs,SIZE(FILTER(c in subs WHERE c.level ="CSEC")) as csecs,SIZE(FILTER(c in subs WHERE) c.level ="CAPE")) 作为斗篷 其中 p.csec_passes <= csecs AND p.cape_passes <= capes
MATCH (p:程序)-[:需要]->(s:主题)

将 p、subs、COLLECT(s) 作为强制项,其中 ALL(n IN 强制项 WHERE n IN subs)
MATCH (p)-[:需要]->(c:组合)-[:包含]->(s:主题)
将 p、c、subs、collect(s) 作为列表
将 p、subs、collect({amt:c.amt, set:list}) 作为组合
WHERE ALL(组合中的组合,其中combo.amt <= size(apoc.coll.intersection(subs,combo.set))) 返回页

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

最佳答案

首先,有一些重要的注意事项。

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

  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

关于neo4j - 重构大型密码联合查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53157501/

相关文章:

solr - 如何将树数据存储在 Lucene/Solr/Elasticsearch 索引或 NoSQL 数据库中?

amazon-web-services - Neo4j 无法在 AWS 实例中启动

performance - Neo4j 密码查询真的很慢

mysql - 使用单独的更新列插入重复键更新批处理

osgi - 嵌入 OSGi 的 Neo4j

javascript - 使用requireJS加载html代码中的 'lib/request'

neo4j - Cypher 查询中的多个 MATCH 子句和逗号之间有什么区别?

neo4j - 如何计算属性之间的差异和百分位数?

使用 Order By 时 MySQL 查询变得非常慢

php - MySQL 选择查询需要一些优化