The CASE expression allows the evaluation of a value, and depending on that value it allows us to output a different expression.
In the case of the query in Mark's blog, we were using the numerical value for the month to drive what day range to use.
The range function is a list function that will output a list of values starting with the provided starting value, and ending at the provided ending value. So range(1,3)
gives us [1,2,3]
, and range(1,31)
gives a list range starting at 1, and going through 31.
For the month of January there are always 31 days, so if we know we're only processing January, and we want to create the :Day nodes for January and connect them, we could do this with a single FOREACH:
MATCH (m:Month {month:1, name:"January"})
FOREACH ( i IN range(1,31) |
CREATE (d:Day {day: i})
CREATE (m)-[:HAS_DAY]->(d) )
But if we want to process every month, we have to iterate over them, needing another FOREACH, and since days are variable per month we need a CASE statement for the range of days to create in the inner FOREACH:
WITH range(1,12) as months
FOREACH(month IN months |
CREATE (m:Month {month: month})
FOREACH(day IN (CASE
WHEN month IN [1,3,5,7,8,10,12] THEN range(1,31) // these months have 31 days
WHEN month = 2 THEN range(1,28) // not working with years, so no leapyear calc, default Feb has 28 days
ELSE range(1,30) // all other months have 30 days
END) |
CREATE (d:Day {day: day})
MERGE (m)-[:HAS_DAY]->(d)))
This is similar to what's on Mark's blog, but since we're not working with years, we don't have enough info to calculate leapyear/leapday for February. Marks' query does deal with specific years, so we can calculation leapyear/leapday, which used a nested CASE.