Neo4j架构非规范化

时间:2015-08-07 07:59:28

标签: neo4j cypher spring-data-neo4j graph-databases

在我的Neo4j应用程序中,我对每种产品都有特定产品的产品,产品特性和投票清单(双重)。

为了按照特征列表的平均权重对产品列表进行排序,我需要执行复杂的运行时Cypher查询,该查询将计算每个产品的特征列表的平均权重总和。

这是我目前的Cypher查询:

MATCH (parentP:Product)-[:CONTAINS]->(childP:Product)
WHERE id(parentP) = {productId}
WITH childP
OPTIONAL MATCH (p:Product)<-[:VOTED_FOR]-(v:Vote)-[:VOTED_ON]->(c:Characteristic)
WHERE id(p) = id(childP) AND id(c) IN {characteristicIds}
WITH childP, c, avg(v.weight) as weight
RETURN childP AS product, sum(weight) as weight
ORDER BY weight DESC

我知道Neo4j对于图遍历非常快,但对聚合(求和,计数,平均等)没有那么好。我的系统可以为每个产品的每个特征提供大量的投票列表。

请帮助我对此结构进行说明,以避免因大量投票而出现任何性能问题。

Brian查询的PROFILE输出:

Cypher版本:CYPHER 2.2,计划者:COST。在1482毫秒内总共有374933次点击命中率。

PROFILE output

3 个答案:

答案 0 :(得分:2)

我不知道我会说Neo4j对聚合没有好处。您可以通过在第二场比赛中专门包括childP来帮助它节省一些工作:

MATCH (parentP)-[:CONTAINS]->(childP:Product)
WHERE id(parentP) = {productId}
OPTIONAL MATCH childP<-[:VOTED_FOR]-(v:Vote)-[:VOTED_ON]->(c)
WHERE id(c) IN {characteristicIds}
WITH childP, c, avg(v.weight) as weight
RETURN childP AS product, sum(weight) as weight
ORDER BY weight DESC

但我想确保理解你所要求的内容。这个查询表现不佳吗?您是否试图阻止它在未来表现不佳?

答案 1 :(得分:0)

如果我们谈论性能问题,附加分析信息会很有用:http://neo4j.com/docs/stable/how-do-i-profile-a-query.html

然后更容易决定在哪里采取行动。

答案 2 :(得分:0)

您也可以尝试:

MATCH (c:Characteristic) WHERE id(c) IN {characteristicIds} 
WITH collect(c) as characteristics

MATCH (parentP:Product)-[:CONTAINS]->(childP:Product)
WHERE id(parentP) = {productId}
OPTIONAL MATCH childP<-[:VOTED_FOR]-(v:Vote)
WITH childP, v, head(filter(c in characteristics WHERE (v)-[:VOTED_ON]->(c))) as c
WHERE c is not null
WITH childP, c, avg(v.weight) as weight
RETURN childP AS product, sum(weight) as weight
ORDER BY weight DESC

由于对产品的投票少于每个特征的投票,我们从这些投票开始,然后检查特征。没有数据库,但很难说。