Tree Neo4j:如何在树形图中聚合属性值?

Tree Neo4j:如何在树形图中聚合属性值?,tree,neo4j,aggregation,Tree,Neo4j,Aggregation,我是Neo4j的新手,在玩Neo4j,看看我们是否可以在我们的一个项目中使用它。假设我创建了如下图形: CREATE (n:PORTFOLIO {NAME:"PF_R", VALUE_RF_A:"0.5"}) CREATE (n:PORTFOLIO {NAME:"PF_A", VALUE_RF_A:"1.0", VALUE_RF_B:"2.0"}) CREATE (n:PORTFOLIO {NAME:"PF_B", VALUE_RF_A:"1.1", VALUE_RF_C:"3.0"}) MA

我是Neo4j的新手,在玩Neo4j,看看我们是否可以在我们的一个项目中使用它。假设我创建了如下图形:

CREATE (n:PORTFOLIO {NAME:"PF_R", VALUE_RF_A:"0.5"})
CREATE (n:PORTFOLIO {NAME:"PF_A", VALUE_RF_A:"1.0", VALUE_RF_B:"2.0"})
CREATE (n:PORTFOLIO {NAME:"PF_B", VALUE_RF_A:"1.1", VALUE_RF_C:"3.0"})

MATCH (r:PORTFOLIO), (a:PORTFOLIO), (b:PORTFOLIO)
WHERE r.NAME="PF_R" AND a.NAME="PF_A" AND b.NAME="PF_B"
CREATE (r)-[s1:has_sub_pf]->(a), (r)-[s2:has_sub_pf]->(b)
RETURN r,a,b
=>问题: 一个(或多个?)用于更改图形的MATCH/SET语句看起来如何,从而使下面的查询返回节点“PF_R”:

因此属性“VALUE_*”在树中从叶子到根向上聚合。 更详细地说:

我希望属性“VALUE_RF_*”从叶子向上聚合(添加)到根(或者添加到下一个更高级别,如果不存在)。具体说明:名为“PF_A”的投资组合节点是一个叶子,因此没有任何变化,但是属性“VALUE_RF_A”和“VALUE_RF_B”应该添加到其父节点,这样名为“PF_R”的投资组合节点的属性“VALUE_RF_A”和“VALUE_RF_B”的值为“1.5”(1.0+0.5)和“2.0”(尚未存在)。同时(或之后),名为“PF_B”的(leaf)投资组合节点的属性“VALUE_rfu A”和“VALUE_RF_C”也应添加到节点“PF_R”的属性中,以便最终拥有值为“2.6”、“2.0”和“VALUE_RF_C”的属性“VALUE_rfu A”、“VALUE_RF_B”和“VALUE_RF_C”

哦,顺便说一句: 如果这只需要一个语句,而不是每个(根)->叶路径,那么这将是完美的。可能的方法是在树的每个“层”上进行这样的聚合,从叶子开始,向上到双亲。 如果要使用的语句不依赖于属性的特定名称,而只聚合具有相同名称的属性的值,那就更好了(顺便说一句,我还有另一个问题:我能在树中找到具有相同名称的属性的节点吗:Neo4J中有没有办法查询“元”/“模式信息”


谢谢你的支持

我将您的问题解释为,对于树结构中的节点,如何将高阶节点的属性设置为其低阶节点的属性之和。我不确定您是否只关心反映其叶和枝之和的根节点,或者是否需要每个相对上级反映其下级之和。您没有提到树的深度(您的示例有一个根和两个叶),也没有提到树中的任何节点是否可以贡献值或仅贡献叶,因此我将给出一个您必须应用于您的结构的一般答案

在树的根中求和的通用模式可以是

MATCH (root:Root)-[:BRANCH*]->(b) // N.B. label the root so you can better control the starting point of your pattern
WITH root, SUM(b.value) as value
SET root.value = value
如果根还包含您可以执行的值

SET root.sum = root.value + value
保留
root.value
不变。你必须弄清楚这些节点和值是什么——我将在下面假设树中的任何节点,不仅仅是叶子,都可以有真实的值,所以我将把节点的值与其相对树的和分开。如果求和操作改变了求和的值,则在第二次运行时会给出不同的结果,这可能是不需要的

对上级中的直接下级进行求和的通用模式类似,但对根没有标签限制,也没有删除关系中的可变深度修饰符

MATCH (superior)-[:BRANCH]->(inferior)
WITH superior, SUM(inferior.value) as sum
SET superior.sum = superior.value + sum
这个查询在传递性方面做得不好,因为它只获取下级的值,而不是它们的和,如果要获取和,它将根据计算这些局部和的顺序得到不同的和——由于首先计算的是较浅的和,因此倾向于在结构中更深层地释放值。如果用于设置中间节点的和,则第一个查询的情况正好相反,这里的风险是嵌套越深的值首先求和,然后在较浅的和中表示两次

要使树中的每个中间节点在任何深度对其所有从属节点求和,但不重复计算或丢失值,您可以使用局部求和查询,只需要施加正确的顺序。一种方法是匹配树中任何深度的所有路径,对于这样一条路径的每个端点节点,将其作为一个局部上级匹配到其局部下级(
b
l
)。然后收集每个上级的下级,并按路径长度对结果排序,确保首先处理树中最深的模式。然后从次节点中累积正确的和。如果下级是叶子,他们没有自己的总和,所以使用他们的价值,否则使用总和;如果任何节点缺少值,则使用0。这由
COALESCE
处理。每个节点的值都包含在其自身的总和中,但这取决于您。通过对
匹配的结果进行排序
并不是在遍历时而是在设置属性时进行累加,您可以期望聚合以正确的顺序逐步遍历树

MATCH path=(r:Root)-[:BRANCH*0..]->(b), b-[:BRANCH]->l
WITH b, length(path) as depth, collect(l) as ls
ORDER BY depth desc
SET b.sum = REDUCE(acc = COALESCE(b.value,0), l IN ls | acc + COALESCE(l.sum, l.value, 0))
RETURN ID(b) AS id, depth, b.sum AS sum
下面是一个用于尝试查询的示例。树中的某些节点具有value属性,而有些节点不具有value属性

这应该适用于一个或多个树,只需标记根节点即可

不要将数值设置为字符串:
“1.0”+“2.0”=“1.02.0”


如果不显式地命名属性,就没有直接的方法可以做到这一点。可能有一些解决办法,但你必须单独提出问题。

在我上面的最后一句话之后-这是我尝试的(但也没有成功):


备注:从根到(叶)叶公文包的每个节点都有一个属性值。我仅为叶节点将此属性设置为1,然后尝试使用此语句将它们聚合/相加到根(好的,根可能需要最后一条额外语句,但对于每个内部节点,都应该有value_a!=0,对吗?

在我的示例中,即使没有额外的“sum_值”,以下语句也有助于获得我的解决方案财产:

MATCH path=(r:ROOT)-[:has_sub_pf*0..]->(p), p-[:has_sub_pf]->l
WITH p, length(path) as depth, collect(l) as ls
ORDER BY depth desc
SET p.value_a = REDUCE(acc = COALESCE(p.value_a,0), x IN ls | acc + x.value_a)
RETURN ID(p) AS id, depth, p.sum_a AS sum

非常感谢

你想干什么?有大量的
MATCH
/
SET
语句会改变gr
MATCH path=(r:ROOT)-[:has_sub_pf*0..]->(p), p-[:has_sub_pf]->(l:PORTFOLIO)
WITH p, length(path) as depth, sum(l.value_b) as sum_value
ORDER BY depth desc
SET p.value_b=sum_value
MATCH path=(r:ROOT)-[:has_sub_pf*0..]->(p), p-[:has_sub_pf]->l
WITH p, length(path) as depth, collect(l) as ls
ORDER BY depth desc
SET p.value_a = REDUCE(acc = COALESCE(p.value_a,0), x IN ls | acc + x.value_a)
RETURN ID(p) AS id, depth, p.sum_a AS sum