Neo4j模式非规范化

Neo4j模式非规范化,neo4j,cypher,spring-data-neo4j,graph-databases,Neo4j,Cypher,Spring Data Neo4j,Graph Databases,在我的Neo4j应用程序中,我有一个产品、产品特征和投票列表(双倍权重),每个产品都有一个特定的特征 为了根据特征列表的平均投票权对产品列表进行排序,我需要执行复杂的运行时密码查询,该查询将计算每个产品特征列表的平均权重之和 这是我当前的密码查询: MATCH (parentP:Product)-[:CONTAINS]->(childP:Product) WHERE id(parentP) = {productId} WITH childP OPTIONAL MATCH (p:Produc

在我的Neo4j应用程序中,我有一个产品、产品特征和投票列表(双倍权重),每个产品都有一个特定的特征

为了根据特征列表的平均投票权对产品列表进行排序,我需要执行复杂的运行时密码查询,该查询将计算每个产品特征列表的平均权重之和

这是我当前的密码查询:

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
MATCH(parentP:Product)-[:CONTAINS]->(childP:Product)
其中id(parentP)={productId}
和childP
可选匹配(p:产品)(c:特性)
其中,{characteristicds}中的id(p)=id(childP)和id(c)
以childP、c、avg(v.重量)作为重量
返回childP作为乘积,总和(重量)作为重量
按重量说明订购
我知道Neo4j对于图形遍历来说非常快,但是对于聚合(求和、计数、平均等)来说就没有那么好了。我的系统可以为每个产品上的每个特性提供一个大的投票列表

请帮助我取消此结构的限制,以避免出现大量投票的性能问题

Brian查询的配置文件输出:

密码版本:密码2.2,计划者:成本。1482毫秒内374933 db总命中率


我不知道我会说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
MATCH(parentP)-[:CONTAINS]->(childP:Product)
其中id(parentP)={productId}
可选匹配childP(c)
其中,{characteristicds}中的id(c)
以childP、c、avg(v.重量)作为重量
返回childP作为乘积,总和(重量)作为重量
按重量说明订购

不过,我想确定我明白你的要求。此查询是否执行得很差?您是否试图防止它在将来表现不佳?

如果我们谈论的是性能问题,请附上分析信息:

这样就更容易决定在哪里采取行动。

您也可以尝试:

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
匹配(c:Characteristic),其中id(c)位于{characteristicds}
以collect(c)为特征
匹配(parentP:Product)-[:CONTAINS]->(childP:Product)
其中id(parentP)={productId}
可选将childP(c)))匹配为c
其中c不是null
以childP、c、avg(v.重量)作为重量
返回childP作为乘积,总和(重量)作为重量
按重量说明订购

由于对一个产品的投票比对每个特征的投票要少得多,我们从这些开始,然后对照特征进行检查。如果没有db,很难说。

谢谢你的回答!Rik Van Bruggen的“Learning Neo4j”电子书中提到了聚合性能(第40页)-“如果您试图将不需要大量加入或需要大量聚合(求和、计数、平均等)的大量内容、有效集合放在一起在这些集合上,图形数据库的性能与其他数据库管理系统相比将不会那么好。”此外,当我为每个产品的每个特征添加1个投票时,一切都正常。如果每个产品的每个特性都有100张选票,我可以看到速度的放缓。是的,我想与其他一些数据库相比,速度会慢一些。我同意阿尔伯特的观点,你应该做一些分析。我要做的另一件事是在我的查询中用s将
更改为
RETURN
s,并删除其余部分,以查看性能缓慢的地方。也许您可以为Brian的查询附加一个查询计划,用于慢速情况?您可以在shell或浏览器中使用配置文件预先结束查询。当然,我已将带有查询计划的图像添加到我的问题正文中。也许您可以共享帮助我们执行查询的示例数据库?我已添加示例数据库和查询您希望查询运行的速度有多快?我在您的数据库上的第一次运行花费了2.1秒,在第一次查询之后大约花费了0.5秒。这是一个小样本数据库。。真正的数据库要大得多。。我想使此模式/查询独立于投票列表大小的性能此查询的配置文件输出-Cypher版本:Cypher 2.2,planner:COST。1624443在4303毫秒内的总db命中率。我希望它将使用优化的
ExpandInto
操作来处理这部分`其中(v)-[:投票]->(c)`但仍然没有示例数据库,很难帮助:)