这是我上一个问题的后续问题:Correct way to create json from neo4j rest API。
我能够通过@Michael Hunger提供给我的帮助,以我所要求的格式获得JSON。以下是代码:
MATCH (mainCap:Capability{SectorID:"PNU"})
OPTIONAL MATCH (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)
OPTIONAL MATCH (adoptsCap1)-[r2:KPI_Capability]->(capKPI)
OPTIONAL MATCH (adoptsCap1)-[r4:Capability_Capability]->(cap1)
OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
OPTIONAL MATCH (cap1)-[r6:KPI_Capability]->(KPI1)
OPTIONAL MATCH (cap1)-[r7:Capability_Capability]->(cap2)
OPTIONAL MATCH (cap2)<-[r8:Capability_Capability]-(isPart2)
OPTIONAL MATCH (cap2)-[r9:KPI_Capability]->(KPI2)
OPTIONAL MATCH (cap2)-[r10:Capability_Capability]->(cap3)
OPTIONAL MATCH (cap3)<-[r11:Capability_Capability]-(isPart3)
OPTIONAL MATCH (cap3)-[r12:KPI_Capability]->(KPI3)
OPTIONAL MATCH (mainCap)<-[r3:Capability_Capability]-(isPart:Capability)
with
mainCap as mainCap,
isPart as isPart,
adoptsCap1 as adoptsCap1,
cap1 as cap1,
cap2 as cap2,
cap3 as cap3,
KPI2 as KPI2,
isPart2 as isPart2,
KPI1 as KPI1,
isPart1 as isPart1,
capKPI as capKPI,
CASE WHEN KPI3 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: KPI3.ExternalID,
type: labels(KPI3)[0],
name: KPI3.Name,
description: KPI3.Description,
sectorID: KPI3.SectorID,
CCO: KPI3.CCO,
CFO: KPI3.CFO,
SVPHR: KPI3.SVPHR,
area: KPI3.Area,
CEO: KPI3.CEO,
CIO: KPI3.CIO,
COO: KPI3.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn3,
CASE WHEN isPart3 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart3.ExternalID,
type: labels(isPart3)[0]
}
)
ELSE
[]
END as isPartOfCapability3
with
mainCap as mainCap,
isPart as isPart,
adoptsCap1 as adoptsCap1,
cap1 as cap1,
cap2 as cap2,
KPI1 as KPI1,
isPart1 as isPart1,
capKPI as capKPI,
CASE WHEN cap3 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: cap3.ExternalID,
type: labels(cap3)[0],
name: cap3.Name,
description: cap3.Overview,
sectorID: cap3.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn3,
isPartOfCapability:isPartOfCapability3
}
)
ELSE
[]
END as consistsOfCapability3,
CASE WHEN KPI2 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: KPI2.ExternalID,
type: labels(KPI2)[0],
name: KPI2.Name,
description: KPI2.Description,
sectorID: KPI2.SectorID,
CCO: KPI2.CCO,
CFO: KPI2.CFO,
SVPHR: KPI2.SVPHR,
area: KPI2.Area,
CEO: KPI2.CEO,
CIO: KPI2.CIO,
COO: KPI2.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn2,
CASE WHEN isPart2 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart2.ExternalID,
type: labels(isPart2)[0]
}
)
ELSE
[]
END as isPartOfCapability2
with mainCap as mainCap,
adoptsCap1 as adoptsCap1,
isPart as isPart,
cap1 as cap1,
capKPI as capKPI,
CASE WHEN cap2 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: cap2.ExternalID,
type: labels(cap2)[0],
name: cap2.Name,
description: cap2.Overview,
sectorID: cap2.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn2,
isPartOfCapability:isPartOfCapability2,
consistsOfCapability:consistsOfCapability3
}
)
ELSE
[]
END as consistsOfCapability2,
CASE WHEN KPI1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: KPI1.ExternalID,
type: labels(KPI1)[0],
name: KPI1.Name,
description: KPI1.Description,
sectorID: KPI1.SectorID,
CCO: KPI1.CCO,
CFO: KPI1.CFO,
SVPHR: KPI1.SVPHR,
area: KPI1.Area,
CEO: KPI1.CEO,
CIO: KPI1.CIO,
COO: KPI1.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn1,
CASE WHEN isPart1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart1.ExternalID,
type: labels(isPart1)[0]
}
)
ELSE
[]
END as isPartOfCapability1
with mainCap as mainCap,
adoptsCap1 as adoptsCap1,
isPart as isPart,
CASE WHEN cap1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: cap1.ExternalID,
type: labels(cap1)[0],
name: cap1.Name,
description: cap1.Overview,
sectorID: cap1.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn1,
isPartOfCapability:isPartOfCapability1,
consistsOfCapability:consistsOfCapability2
}
)
ELSE
[]
END as consistsOfCapability1,
CASE WHEN capKPI IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: capKPI.ExternalID,
type: labels(capKPI)[0],
name: capKPI.Name,
description: capKPI.Description,
sectorID: capKPI.SectorID,
CCO: capKPI.CCO,
CFO: capKPI.CFO,
SVPHR: capKPI.SVPHR,
area: capKPI.Area,
CEO: capKPI.CEO,
CIO: capKPI.CIO,
COO: capKPI.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn
return {
_id:mainCap.ExternalID,
type:labels(mainCap)[0],
name:mainCap.Name,
adoptsCapability:
CASE WHEN adoptsCap1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: adoptsCap1.ExternalID,
type: labels(adoptsCap1)[0],
name: adoptsCap1.Name,
description: adoptsCap1.Overview,
sectorID: adoptsCap1.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn,
consistsOfCapability:consistsOfCapability1
}
)
ELSE
[]
END,
isPartOfCapability:
CASE WHEN isPart IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart.ExternalID,
type: labels(isPart)[0]
}
)
ELSE
[]
END
}as `col2`
以上查询采用 4149 ms 来提供结果。我尝试使用distinct进行优化。通过: http://thought-bytes.blogspot.com/2013/01/optimizing-neo4j-cypher-queries.html。 Optimize Neo4j Cypher query 更相关:Optimizing Cypher queries with lots of optional relationships
问题:是否可以优化并将时间缩短到约2秒左右?我有一个angularjs UI,它有一个菜单绑定来自neo的数据。它目前需要4.4秒才能从neo获取数据或者这是我可以从这个查询中获得的最大性能吗?
帮助表示感谢。谢谢
以下是解决方案:
重新格式化查询后,性能大幅提升。基数导致性能滞后。 从4149毫秒下降到400毫秒:
match (mainCap:Capability{SectorID:"PNU"})
OPTIONAL MATCH (mainCap:Capability)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)
OPTIONAL MATCH (adoptsCap1)-[r2:KPI_Capability]->(capKPI)
OPTIONAL MATCH (adoptsCap1)-[r4:Capability_Capability]->(cap1)
with mainCap, adoptsCap1, cap1,
CASE WHEN capKPI IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: capKPI.ExternalID,
type: labels(capKPI)[0],
name: capKPI.Name,
description: capKPI.Description,
sectorID: capKPI.SectorID,
CCO: capKPI.CCO,
CFO: capKPI.CFO,
SVPHR: capKPI.SVPHR,
area: capKPI.Area,
CEO: capKPI.CEO,
CIO: capKPI.CIO,
COO: capKPI.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn
OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
OPTIONAL MATCH (cap1)-[r6:KPI_Capability]->(KPI1)
OPTIONAL MATCH (cap1)-[r7:Capability_Capability]->(cap2)
with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,
CASE WHEN KPI1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: KPI1.ExternalID,
type: labels(KPI1)[0],
name: KPI1.Name,
description: KPI1.Description,
sectorID: KPI1.SectorID,
CCO: KPI1.CCO,
CFO: KPI1.CFO,
SVPHR: KPI1.SVPHR,
area: KPI1.Area,
CEO: KPI1.CEO,
CIO: KPI1.CIO,
COO: KPI1.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn1,
CASE WHEN isPart1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart1.ExternalID,
type: labels(isPart1)[0]
}
)
ELSE
[]
END as isPartOfCapability1
OPTIONAL MATCH (cap2)<-[r8:Capability_Capability]-(isPart2)
OPTIONAL MATCH (cap2)-[r9:KPI_Capability]->(KPI2)
OPTIONAL MATCH (cap2)-[r10:Capability_Capability]->(cap3)
with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,cap3,
CASE WHEN KPI2 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: KPI2.ExternalID,
type: labels(KPI2)[0],
name: KPI2.Name,
description: KPI2.Description,
sectorID: KPI2.SectorID,
CCO: KPI2.CCO,
CFO: KPI2.CFO,
SVPHR: KPI2.SVPHR,
area: KPI2.Area,
CEO: KPI2.CEO,
CIO: KPI2.CIO,
COO: KPI2.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn2,
CASE WHEN isPart2 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart2.ExternalID,
type: labels(isPart2)[0]
}
)
ELSE
[]
END as isPartOfCapability2
OPTIONAL MATCH (cap3)<-[r11:Capability_Capability]-(isPart3)
OPTIONAL MATCH (cap3)-[r12:KPI_Capability]->(KPI3)
with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,cpbltyIsMsrdByKpiPttrn2,isPartOfCapability2,cap3,
CASE WHEN KPI3 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: KPI3.ExternalID,
type: labels(KPI3)[0],
name: KPI3.Name,
description: KPI3.Description,
sectorID: KPI3.SectorID,
CCO: KPI3.CCO,
CFO: KPI3.CFO,
SVPHR: KPI3.SVPHR,
area: KPI3.Area,
CEO: KPI3.CEO,
CIO: KPI3.CIO,
COO: KPI3.COO
}
)
ELSE
[]
END as cpbltyIsMsrdByKpiPttrn3,
CASE WHEN isPart3 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart3.ExternalID,
type: labels(isPart3)[0]
}
)
ELSE
[]
END as isPartOfCapability3
with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,cpbltyIsMsrdByKpiPttrn2,isPartOfCapability2,
CASE WHEN cap3 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: cap3.ExternalID,
type: labels(cap3)[0],
name: cap3.Name,
description: cap3.Overview,
sectorID: cap3.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn3,
isPartOfCapability:isPartOfCapability3
}
)
ELSE
[]
END as consistsOfCapability3
with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,
CASE WHEN cap2 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: cap2.ExternalID,
type: labels(cap2)[0],
name: cap2.Name,
description: cap2.Overview,
sectorID: cap2.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn2,
isPartOfCapability:isPartOfCapability2,
consistsOfCapability:consistsOfCapability3
}
)
ELSE
[]
END as consistsOfCapability2
with mainCap, adoptsCap1, cpbltyIsMsrdByKpiPttrn,
CASE WHEN cap1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: cap1.ExternalID,
type: labels(cap1)[0],
name: cap1.Name,
description: cap1.Overview,
sectorID: cap1.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn1,
isPartOfCapability:isPartOfCapability1,
consistsOfCapability:consistsOfCapability2
}
)
ELSE
[]
END as consistsOfCapability1
OPTIONAL MATCH (mainCap)<-[r3:Capability_Capability]-(isPart:Capability)
return {
model:{
_id:mainCap.ExternalID,
type:labels(mainCap)[0],
name:mainCap.Name,
adoptsCapability:
CASE WHEN adoptsCap1 IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: adoptsCap1.ExternalID,
type: labels(adoptsCap1)[0],
name: adoptsCap1.Name,
description: adoptsCap1.Overview,
sectorID: adoptsCap1.SectorID,
cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn,
consistsOfCapability:consistsOfCapability1
}
)
ELSE
[]
END,
isPartOfCapability:
CASE WHEN isPart IS NOT NULL THEN
COLLECT(DISTINCT
{
_id: isPart.ExternalID,
type: labels(isPart)[0]
}
)
ELSE
[]
END
}
}
答案 0 :(得分:1)
用于您的起始节点:
CREATE CONSTRAINT ON (mainCap:Capability) assert mainCap.SectorID IS UNIQUE;
或
CREATE INDEX ON :Capability(SectorID);
最重要的一点是让你的中间基数降低。
否则,前一个语句产生的每一行都会重复匹配,无论它是否是重复的行。
MATCH (mainCap:Capability{SectorID:"PNU"})
OPTIONAL MATCH (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)-[r2:KPI_Capability]->(capKPI),
OPTIONAL MATCH (adoptsCap1)-[r4:Capability_Capability]->(cap1)
// reduce cardinality
with mainCap, adoptsCap1, cap1, collect(distinct capKPI) as _capKPI
OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
with mainCap, adoptsCap1, cap1, _capKPI, collect(isPart1) as _isPart1
...
PS如果名称没有像mainCap as mainCap,
并尝试从顶部开始,随时进行剖析。
答案 1 :(得分:0)
根据您使用的Neo4j版本(在2.2.0之前或之后),尝试快速尝试:
尝试合并所有OPTIONAL MATCH
条款,如下所示:
MATCH (mainCap:Capability{SectorID:"PNU"})
OPTIONAL MATCH
(mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1),
(adoptsCap1)-[r2:KPI_Capability]->(capKPI),
(adoptsCap1)-[r4:Capability_Capability]->(cap1),
(cap1)<-[r5:Capability_Capability]-(isPart1),
(cap1)-[r6:KPI_Capability]->(KPI1),
(cap1)-[r7:Capability_Capability]->(cap2),
(cap2)<-[r8:Capability_Capability]-(isPart2),
(cap2)-[r9:KPI_Capability]->(KPI2),
(cap2)-[r10:Capability_Capability]->(cap3),
(cap3)<-[r11:Capability_Capability]-(isPart3),
(cap3)-[r12:KPI_Capability]->(KPI3),
(mainCap)<-[r3:Capability_Capability]-(isPart:Capability)
而不是:
MATCH (mainCap:Capability{SectorID:"PNU"})
OPTIONAL MATCH (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)
OPTIONAL MATCH (adoptsCap1)-[r2:KPI_Capability]->(capKPI)
OPTIONAL MATCH (adoptsCap1)-[r4:Capability_Capability]->(cap1)
OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
OPTIONAL MATCH (cap1)-[r6:KPI_Capability]->(KPI1)
OPTIONAL MATCH (cap1)-[r7:Capability_Capability]->(cap2)
OPTIONAL MATCH (cap2)<-[r8:Capability_Capability]-(isPart2)
OPTIONAL MATCH (cap2)-[r9:KPI_Capability]->(KPI2)
OPTIONAL MATCH (cap2)-[r10:Capability_Capability]->(cap3)
OPTIONAL MATCH (cap3)<-[r11:Capability_Capability]-(isPart3)
OPTIONAL MATCH (cap3)-[r12:KPI_Capability]->(KPI3)
OPTIONAL MATCH (mainCap)<-[r3:Capability_Capability]-(isPart:Capability)
修改强>
我没有仔细阅读查询,因为我打算打电话,但你也可以将它们组合起来:
OPTIONAL MATCH (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)-[r2:KPI_Capability]->(capKPI)
Neo4j非常聪明,无论如何都能很好地处理它,所以它是一种风格选择。