Search code examples
neo4jcypherpy2neo

Creating a Neo4j Date Tree that will work with py2neo


I'm trying to build a date tree in my Neo4j database that will work with the calendar module in Nigel Small's py2neo library.

I used Mark Needham's starter code from here (http://java.dzone.com/articles/neo4j-cypher-creating-time), but that doesn't connect all of the Year nodes to a master calendar node, which is required for the py2neo library. (docs here: http://book.py2neo.org/en/latest/calendar/)

I've modified Mark's code to try and create a master node to connect all of the years like this:

CREATE (x:Calendar {name:'master'})
WITH range(2005, 2014) AS years, range(1,12) as months
FOREACH(year IN years | 
  CREATE (y:Year {year: year})
  MERGE (x)-[:YEAR]->(y)
  FOREACH(month IN months | 
    CREATE (m:Month {month: month})
    MERGE (y)-[:MONTH]->(m)
    FOREACH(day IN (CASE 
                      WHEN month IN [1,3,5,7,8,10,12] THEN range(1,31) 
                      WHEN month = 2 THEN 
                        CASE
                          WHEN year % 4 <> 0 THEN range(1,28)
                          WHEN year % 100 <> 0 THEN range(1,29)
                          WHEN year % 400 <> 0 THEN range(1,29)
                          ELSE range(1,28)
                        END
                      ELSE range(1,30)
                    END) |      
      CREATE (d:Day {day: day})
      MERGE (m)-[:DAY]->(d))))

What's happening is that there's a node (with Calendar label) that's getting created but no relationships attached to it, while there's a node (with no label) that's getting created and attached to each Year node.

I know this is probably a really easy fix, but I'm new to CYPHER and am really struggling to figure this out.


Solution

  • You forgot to transport the calendar master "x" through the WITH

    CREATE (master:Calendar { name:'master' })
    WITH range(2005,2014) AS years, range(1,12) AS months,master
    FOREACH (year IN years | 
             CREATE (y:Year { year: year })
             MERGE (master)-[:YEAR]->(y)
             FOREACH (month IN months | 
                      CREATE (m:Month { month: month })
                      MERGE (y)-[:MONTH]->(m)
                      FOREACH (day IN (
                        CASE
                        WHEN month IN [1,3,5,7,8,10,12]
                        THEN range(1,31)
                        WHEN month = 2
                        THEN
                        CASE
                        WHEN year % 4 <> 0
                        THEN range(1,28)
                        WHEN year % 100 <> 0
                        THEN range(1,29)
                        WHEN year % 400 <> 0
                        THEN range(1,29)
                        ELSE range(1,28) END ELSE range(1,30) END )| 
                               CREATE (d:Day { day: day })
                               MERGE (m)-[:DAY]->(d))))