2016-10-29 139 views
0

有两种节点类型,AccountTransfer。 A Transfer表示资金在Account节点之间的移动。节点可以有任意数量的输入和输出节点。例如,三个Accounts可能会以任何方式向其他16个Accounts发送40美元(合计120美元),并且它可以工作。Neo4j/Cypher:返回节点本身内节点之间关系值的总和

Transfer对象没有发送或接收的资金总和 - 它们只存储在关系本身中。我想在密码查询中计算这个值,并将其作为返回的Transfer对象的一部分返回,不是单独的。 (类似于SQL JOIN)

我是Neo4j + Cypher的新手;到目前为止,我已经得到了查询是这样的:

MATCH (tf:Transfer {id:'some_id'}) 
MATCH (tf)<-[in:IN_TO]-(in_account:Account) 
MATCH (tf)-[out:OUT_TO]->(out_account:Account) 
RETURN tf,in_account,in,out_account,out, sum(in.value) as sum_in, sum(out.value) as sum_out 

如果我管理这个数据库,我只是预先计算的款项,并将其存储在Transfer性能 - 但是这不是在这个时候的选项。

TL;博士:我想存储sum_insum_out在返回tf对象。

回答

0

当您使用像SUM这样的聚合时,必须将聚合的别名保留在结果行之外,否则最终会得到单行总和。这会帮助你得到的东西更接近你想要的东西,包括你的动态属性分配的解决方法:

CREATE (temp) 
WITH temp 
MATCH (tf:Transfer {id:'some_id'}) 
MATCH (tf)<-[in:IN_TO]-(in_account:Account) 
MATCH (tf)-[out:OUT_TO]->(out_account:Account) 
SET temp += PROPERTIES(tf) 
WITH temp, SUM(in.value) AS sum_in, SUM(out.value) AS sum_out, COLLECT(in_account) AS in_accounts, COLLECT(out_account) AS out_accounts 
SET temp.sum_in = sum_in 
SET temp.sum_out = sum_out 
WITH temp, PROPERTIES(temp) AS props, in_accounts, out_accounts 
DELETE temp 
RETURN props, in_accounts, out_accounts 

您正在创建一个虚拟节点保留的属性,因为这是动态分配的属性现有地图的唯一途径或者类似地图,但节点将永远不会被提交给图。此查询应返回:Transfer的属性的Map,包含输入和输出,以及输入和输出帐户的列表,以防您需要对其进行任何额外的工作。

+0

h/t到Gábor的错字接收。 –

0

Tore Eschliman的回答很有洞察力,特别是在聚合别名的属性上。

我想出了一个更骇人的解决方案,可以在这种情况下工作。

实施例的数据集:

CREATE 
    (a1:Account), 
    (a2:Account), 
    (a3:Account), 
    (tf:Transfer), 
    (a1)-[:IN_TO {value: 110}]->(tf), 
    (a2)-[:IN_TO {value: 230}]->(tf), 
    (tf)-[:OUT_TO {value: 450}]->(a3) 

查询:

MATCH (in_account:Account)-[in:IN_TO]->(tf:Transfer) 
WITH tf, SUM(in.value) AS sum_in 
SET tf.sum_in = sum_in 
RETURN tf 
UNION 
MATCH (tf:Transfer)-[out:OUT_TO]->(out_account:Account) 
WITH tf, SUM(out.value) AS sum_out 
SET tf.sum_out = sum_out 
RETURN tf 

结果:

╒═══════════════════════════╕ 
│tf       │ 
╞═══════════════════════════╡ 
│{sum_in: 340, sum_out: 450}│ 
└───────────────────────────┘ 

注意UNION执行一组联合(相对于UNION ALL,其执行多集/ bag union),因此我们不会在结果中有重复。

更新:正如Tore Eschliman在评论中指出的,该解决方案将修改数据库。作为一种解决方法,您可以收集结果并在事后中止交易。

+0

这将永久性地改变':Transfer'节点。 –

+0

好点。我试图解决它,但似乎这不是解决问题的好方向。我现在对解决方案非常感兴趣,但是我无法使用示例数据集处理查询:如果使用'DELETE temp',结果行将充满空值和空值集合。如果你删除'DELETE temp',它就像一个魅力。 (我正在使用Neo4j 3.0.4。) –

+0

你是绝对正确的,我忘了最重要的部分。您必须在删除之前将“PROPERTIES(n)”指定给另一个别名,否则它将消失。 –