Last active
June 26, 2022 08:53
-
-
Save rvanbruggen/9858758 to your computer and use it in GitHub Desktop.
A gist to demonstrate the power of Neo4j for dealing with hierarchical data.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Let's create the top of the tree, the PRODUCT | |
create (n1:PRODUCT {id:1}); | |
//Let's create 100 children of the PRODUCT, COST_GROUPS connected to the top of the tree | |
match (n1:PRODUCT {id:1}) | |
with range(1,100) as RANGE, n1 | |
foreach (r in RANGE | create (n2:COST_GROUP {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n1) ); | |
//for every COST_GROUP, let's connect 100 children at a 3rd level, the COST_TYPEs | |
match (n2:COST_GROUP) | |
with range(1,100) as RANGE, n2 | |
foreach (r in RANGE | create (n3:COST_TYPE {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n2) ); | |
//for every COST_TYPE, connect 10 COST_SUBTYPEs | |
match (n3:COST_TYPE) | |
with range(1,10) as RANGE, n3 | |
foreach (r in RANGE | create (n4:COST_SUBTYPE {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n3) ); | |
//for every COST_SUBTYPE, connect 5 different COSTs | |
match (n4:COST_SUBTYPE) | |
with range(1,5) as RANGE, n4 | |
foreach (r in RANGE | create (n5:COST {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n4) ); | |
//for every COST, connect 3 COST_COMPONENTs | |
match (n5:COST) | |
create (n6:COST_COMPONENT {id:1,price:round(rand()*1000)})-[:PART_OF {quantity:round(rand()*100)}]->(n5); | |
match (n5:COST) | |
create (n6:COST_COMPONENT {id:2,price:round(rand()*1000)})-[:PART_OF {quantity:round(rand()*100)}]->(n5); | |
match (n5:COST) | |
create (n6:COST_COMPONENT {id:3,price:round(rand()*1000)})-[:PART_OF {quantity:round(rand()*100)}]->(n5); | |
//(re-)adding price information to Level 6 | |
match (n6:COST_COMPONENT) | |
set n6.price=round(rand()*1000); | |
//Check the graph to see if right numbers have been added | |
match (n) return labels(n) as Label, count(n); | |
//calculating price based on full sweep of the tree | |
match (n1:PRODUCT {id:1})<-[r1]-(:COST_GROUP)<-[r2]-(:COST_TYPE)<-[r3]-(:COST_SUBTYPE)<-[r4]-(:COST)<-[r5]-(n6:COST_COMPONENT) | |
return sum(r1.quantity*r2.quantity*r3.quantity*r4.quantity*r5.quantity*n6.price) as CalculatedPrice; | |
//calculate intermediate pricing at the COST level | |
match (n5:COST)<-[r5]-(n6:COST_COMPONENT) | |
with n5, sum(r5.quantity*n6.price) as Sum | |
set n5.price=Sum; | |
//calculate intermediate pricing at the COST-SUBTYPE level | |
match (n4:COST_SUBTYPE)<-[r4]-(n5:COST) | |
with n4,sum(r4.quantity*n5.price) as Sum | |
set n4.price=Sum; | |
//calculate intermediate pricing at the COST-TYPE level | |
match (n3:COST_TYPE)<-[r3]-(n4:COST_SUBTYPE) | |
with n3,sum(r3.quantity*n4.price) as Sum | |
set n3.price=Sum; | |
//calculate intermediate pricing at the COST-GROUP level | |
match (n2:COST_GROUP)<-[r2]-(n3:COST_TYPE) | |
with n2,sum(r2.quantity*n3.price) as Sum | |
set n2.price=Sum; | |
//calculate intermediate pricing at the PRODUCT level | |
match (n1:PRODUCT)<-[r1]-(n2:COST_GROUP) | |
with n1, sum(r1.quantity*n2.price) as Sum | |
set n1.price=Sum; | |
//calculate pricing using intermediate pricing levels at the COST-GROUP level | |
match (n1:PRODUCT {id:1})<-[r1]-(n2:COST_GROUP) | |
return sum(r1.quantity*n2.price); | |
//calculate pricing using intermediate pricing levels at the COST-TYPE level | |
match (n1:PRODUCT {id:1})<-[r1]-(n2:COST_GROUP)<-[r2]-(n3:COST_TYPE) | |
return sum(r1.quantity*r2.quantity*n3.price); | |
//Changing the price of ONE COST_COMPONENT | |
match (n6:COST_COMPONENT) | |
with n6, n6.price as OLDPRICE limit 1 | |
set n6.price = n6.price*10 | |
with n6.price-OLDPRICE as PRICEDIFF,n6 | |
match n6-[r5:PART_OF]->(n5:COST)-[r4:PART_OF]->(n4:COST_SUBTYPE)-[r3:PART_OF]->(n3:COST_TYPE)-[r2:PART_OF]->(n2:COST_GROUP)-[r1:PART_OF]-(n1:PRODUCT) | |
set n5.price=n5.price+(PRICEDIFF*r5.quantity), | |
n4.price=n4.price+(PRICEDIFF*r5.quantity*r4.quantity), | |
n3.price=n3.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity), | |
n2.price=n2.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity), | |
n1.price=n1.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity*r1.quantity) | |
return PRICEDIFF, n1.price; | |
//Changing the price of ONE HUNDRED COST_COMPONENTS | |
match (n6:COST_COMPONENT) | |
with n6, n6.price as OLDPRICE limit 100 | |
set n6.price = round(n6.price*1.05) | |
with n6.price-OLDPRICE as PRICEDIFF,n6 | |
match n6-[r5:PART_OF]->(n5:COST)-[r4:PART_OF]->(n4:COST_SUBTYPE)-[r3:PART_OF]->(n3:COST_TYPE)-[r2:PART_OF]->(n2:COST_GROUP)-[r1:PART_OF]-(n1:PRODUCT) | |
set n5.price=n5.price+(PRICEDIFF*r5.quantity), | |
n4.price=n4.price+(PRICEDIFF*r5.quantity*r4.quantity), | |
n3.price=n3.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity), | |
n2.price=n2.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity), | |
n1.price=n1.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity*r1.quantity) | |
return PRICEDIFF, n1.price; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Let's create the top of the tree, the PRODUCT | |
create (n1:PRODUCT {id:1}); | |
//Let's create 100 children of the PRODUCT, COST_GROUPS connected to the top of the tree | |
match (n1:PRODUCT {id:1}) | |
with range(1,100) as RANGE, n1 | |
foreach (r in RANGE | create (n2:COST_GROUP {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n1) ); | |
//for every COST_GROUP, let's connect 100 children at a 3rd level, the COST_TYPEs | |
USING PERIODIC COMMIT | |
match (n2:COST_GROUP) | |
with range(1,100) as RANGE, n2 | |
foreach (r in RANGE | create (n3:COST_TYPE {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n2) ); | |
//for every COST_TYPE, connect 10 COST_SUBTYPEs | |
USING PERIODIC COMMIT | |
match (n3:COST_TYPE) | |
with range(1,10) as RANGE, n3 | |
foreach (r in RANGE | create (n4:COST_SUBTYPE {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n3) ); | |
//for every COST_SUBTYPE, connect 5 different COSTs | |
USING PERIODIC COMMIT | |
match (n4:COST_SUBTYPE) | |
with range(1,5) as RANGE, n4 | |
foreach (r in RANGE | create (n5:COST {id:r})-[:PART_OF {quantity:round(rand()*100)}]->(n4) ); | |
//for every COST, connect 3 COST_COMPONENTs | |
USING PERIODIC COMMIT | |
match (n5:COST) | |
with range(1,3) as RANGE, n5 | |
foreach (r in RANGE | create (n6:COST_COMPONENT {id:r,price:round(rand()*1000)})-[:PART_OF {quantity:round(rand()*100)}]->(n5)); | |
//(re-)adding price information to Level 6 | |
match (n6:COST_COMPONENT) | |
set n6.price=round(rand()*1000); | |
//Check the graph to see if right numbers have been added | |
match (n) return labels(n) as Label, count(n); | |
//calculating price based on full sweep of the tree | |
match (n1:PRODUCT {id:1})<-[r1]-(:COST_GROUP)<-[r2]-(:COST_TYPE)<-[r3]-(:COST_SUBTYPE)<-[r4]-(:COST)<-[r5]-(n6:COST_COMPONENT) | |
return sum(r1.quantity*r2.quantity*r3.quantity*r4.quantity*r5.quantity*n6.price) as CalculatedPrice; | |
//calculate intermediate pricing at the COST level | |
match (n5:COST)<-[r5]-(n6:COST_COMPONENT) | |
with n5, sum(r5.quantity*n6.price) as Sum | |
set n5.price=Sum; | |
//calculate intermediate pricing at the COST-SUBTYPE level | |
match (n4:COST_SUBTYPE)<-[r4]-(n5:COST) | |
with n4,sum(r4.quantity*n5.price) as Sum | |
set n4.price=Sum; | |
//calculate intermediate pricing at the COST-TYPE level | |
match (n3:COST_TYPE)<-[r3]-(n4:COST_SUBTYPE) | |
with n3,sum(r3.quantity*n4.price) as Sum | |
set n3.price=Sum; | |
//calculate intermediate pricing at the COST-GROUP level | |
match (n2:COST_GROUP)<-[r2]-(n3:COST_TYPE) | |
with n2,sum(r2.quantity*n3.price) as Sum | |
set n2.price=Sum; | |
//calculate intermediate pricing at the PRODUCT level | |
match (n1:PRODUCT)<-[r1]-(n2:COST_GROUP) | |
with n1, sum(r1.quantity*n2.price) as Sum | |
set n1.price=Sum; | |
//calculate pricing using intermediate pricing levels at the COST-GROUP level | |
match (n1:PRODUCT {id:1})<-[r1]-(n2:COST_GROUP) | |
return sum(r1.quantity*n2.price); | |
//calculate pricing using intermediate pricing levels at the COST-TYPE level | |
match (n1:PRODUCT {id:1})<-[r1]-(n2:COST_GROUP)<-[r2]-(n3:COST_TYPE) | |
return sum(r1.quantity*r2.quantity*n3.price); | |
//Changing the price of ONE COST_COMPONENT | |
match (n6:COST_COMPONENT) | |
with n6, n6.price as OLDPRICE limit 1 | |
set n6.price = n6.price*10 | |
with n6.price-OLDPRICE as PRICEDIFF,n6 | |
match n6-[r5:PART_OF]->(n5:COST)-[r4:PART_OF]->(n4:COST_SUBTYPE)-[r3:PART_OF]->(n3:COST_TYPE)-[r2:PART_OF]->(n2:COST_GROUP)-[r1:PART_OF]-(n1:PRODUCT) | |
set n5.price=n5.price+(PRICEDIFF*r5.quantity), | |
n4.price=n4.price+(PRICEDIFF*r5.quantity*r4.quantity), | |
n3.price=n3.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity), | |
n2.price=n2.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity), | |
n1.price=n1.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity*r1.quantity) | |
return PRICEDIFF, n1.price; | |
//Changing the price of ONE HUNDRED COST_COMPONENTS | |
match (n6:COST_COMPONENT) | |
with n6, n6.price as OLDPRICE limit 100 | |
set n6.price = round(n6.price*1.05) | |
with n6.price-OLDPRICE as PRICEDIFF,n6 | |
match n6-[r5:PART_OF]->(n5:COST)-[r4:PART_OF]->(n4:COST_SUBTYPE)-[r3:PART_OF]->(n3:COST_TYPE)-[r2:PART_OF]->(n2:COST_GROUP)-[r1:PART_OF]-(n1:PRODUCT) | |
set n5.price=n5.price+(PRICEDIFF*r5.quantity), | |
n4.price=n4.price+(PRICEDIFF*r5.quantity*r4.quantity), | |
n3.price=n3.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity), | |
n2.price=n2.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity), | |
n1.price=n1.price+(PRICEDIFF*r5.quantity*r4.quantity*r3.quantity*r2.quantity*r1.quantity) | |
return PRICEDIFF, n1.price; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment