Neo4j按创建时间遍历关系,实现指定容量篮子精准填充
在Neo4j中按属性排序遍历关系并处理属性的方案
针对需求——按created时间戳从旧到新遍历COLLECTS关系,为容量100kg的Basket分配苹果(前两个关系全取40kg,第三个取20kg),以下是两种可行的实现方案:
示例数据创建语句
先执行以下Cypher创建测试数据:
CREATE (_0:`Basket` {`size`:100}), (_1:`User` {`name":"Franc"}), (_6:`User` {`name":"Peter"}), (_34:`User` {`name":"Betty"}), (_54:`Fruit` ), (_1)-[:`COLLECTS` {`created":"20221206212715","kilos":40,"type":"Apples"}]->(_54), (_6)-[:`COLLECTS` {`created":"20221206212417","kilos":40,"type":"Apples"}]->(_54), (_34)-[:`COLLECTS` {`created":"20221206212547","kilos":40,"type":"Apples"}]->(_54)
方案一:修改原COLLECTS关系属性
通过新增used_kilos属性记录实际分配的重量,保留原始kilos数据:
// 匹配目标Basket和所有苹果收集关系,按创建时间升序排序 MATCH (b:Basket), (u:User)-[r:COLLECTS]->(f:Fruit) WHERE f.type = "Apples" WITH b, r, u, f ORDER BY r.created ASC // 收集排序后的关系并计算累计重量 WITH b, collect({rel: r, user: u, kilos: r.kilos}) AS sortedRelations UNWIND sortedRelations AS item WITH b, item, sum(item.kilos) OVER (ORDER BY item.rel.created ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS totalKilos // 根据剩余容量计算实际分配重量 WITH b, item, CASE WHEN (b.size - (totalKilos - item.kilos)) >= item.kilos THEN item.kilos ELSE b.size - (totalKilos - item.kilos) END AS allocatedKilos // 仅更新有分配重量的关系 WHERE allocatedKilos > 0 SET item.rel.used_kilos = allocatedKilos // 返回结果验证 RETURN item.user.name, item.rel.created, item.rel.kilos, allocatedKilos
执行后,前两个COLLECTS关系的used_kilos会被设为40,第三个设为20,刚好填满Basket的100kg容量。
方案二:新增Basket与User的分配关系
如果需要保留原COLLECTS关系的完整性,可以新增ALLOCATED关系记录分配信息:
// 匹配目标Basket和所有苹果收集关系,按创建时间升序排序 MATCH (b:Basket), (u:User)-[r:COLLECTS]->(f:Fruit) WHERE f.type = "Apples" WITH b, r, u, f ORDER BY r.created ASC // 收集排序后的用户及重量信息 WITH b, collect({user: u, kilos: r.kilos, created: r.created}) AS sortedUsers UNWIND sortedUsers AS userItem WITH b, userItem, sum(userItem.kilos) OVER (ORDER BY userItem.created ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS totalKilos // 根据剩余容量计算实际分配重量 WITH b, userItem, CASE WHEN (b.size - (totalKilos - userItem.kilos)) >= userItem.kilos THEN userItem.kilos ELSE b.size - (totalKilos - userItem.kilos) END AS allocatedKilos // 新增分配关系(避免重复创建) WHERE allocatedKilos > 0 MERGE (b)-[:ALLOCATED {kilos: allocatedKilos, type: "Apples"}]->(userItem.user) // 返回结果验证 RETURN userItem.user.name, userItem.created, userItem.kilos, allocatedKilos
这个方案不会修改原始关系,所有分配记录都保存在新增的ALLOCATED关系中,更适合需要留存原始数据的场景。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

