How to handle dates in neo4j

后端 未结 4 1134
眼角桃花
眼角桃花 2020-12-15 20:28

I\'m an historian of medieval history and I\'m trying to code networks between kings, dukes, popes etc. over a period of time of about 50 years (from 1220 to 1270) in mediev

相关标签:
4条回答
  • 2020-12-15 21:00

    You can also store the dates in their number representation in the following format: YYYYMMDD

    In your case 12200101 would be Jan 1st 1220 and 12701231 would be Dec 31st 1270.

    It's a useful and readable format and you can perform range searches like:

    MATCH (h:HistoricEvent)
    WHERE h.date >= 12200101 AND h.date < 12701231
    RETURN h
    

    It would also let you order by dates, if you need to.

    0 讨论(0)
  • 2020-12-15 21:01

    The common way to deal with dates in Neo4j is storing them either as a string representation or as millis since epoch (aka msec passed since Jan 01 1970).

    The first approach makes the graph more easily readable the latter allows you to do math e.g. calculate deltas.

    In your case I'd store two properties called validFrom and validTo on the relationships. You queries need to make sure you're looking for the correct time interval.

    E.g. to find the king(s) in charge of France from Jan 01 1220 to Dec 31st 1221 you do:

    MATCH (c:Country{name:'France'})-[r:HAS_KING]->(king)
    WHERE r.validFrom >= -23667123600000 and r.validTo <=-23604051600000
    RETURN king, r.validFrom, r.validTo
    

    addendum

    Since Neo4j 3.0 there's the APOC library which provides couple of functions for converting timestamps to/from human readable date strings.

    0 讨论(0)
  • 2020-12-15 21:03

    Another option for dates that keeps the number of nodes/properties you create fairly low is a linked list years (earliest year of interest - latest year), one of months (1-12), and one of dates in a month (1-31). Then every "event" in your graph can be connected to a year, month, and day. This way you don't have to create a new node for every new combination of a year month and day. You just have a single set of months, one of days, and one year. I scale the numbers to make manipulating them easier like so

    Years are yyyy*10000

    Months are mm*100

    Date are dd

    so if you run a query such as

    match (event)-[:happened]->(t:time) 
    with event,sum(t.num) as date 
    return event.name,date
    order by date
    

    You will get a list of all events in chronological order with dates like Janurary 17th, 1904 appearing as 19040117 (yyyymmdd format)

    Further, since these are linked lists where, for example, ...-(t0:time {num:19040000})-[:precedes]->(t1:time {num:19050000})-... ordering is built into the nodes too.

    This is, so far, how I have liked to do my event dating

    0 讨论(0)
  • 2020-12-15 21:10

    As of Neo4J 3.4, the system handles duration and dates, see the official documentation. See more examples here.

    An example related to the original question: Retrieve the historical events that happened in the last 30 days from now :

    WITH duration({days: 30}) AS duration
    MATCH (h:HistoricEvent)
    WHERE date() - duration < date(h.date)
    RETURN h
    
    0 讨论(0)
提交回复
热议问题