Last active
September 6, 2017 18:52
-
-
Save toraritte/0b209815233d6144bb3e1d525c826e10 to your computer and use it in GitHub Desktop.
testing timelines linked lists instead of timestamps
This file contains hidden or 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
| // based on the book, this is somewhat better but without MERGEs, | |
| // you'll end up with one extra relationship per new timeline. | |
| create | |
| (kilgore:Person {name: "Kilgore"}), | |
| (e1:Event {event: "Become CORE student"}), | |
| (e2:Event {event: "Called SFTB"}), | |
| (e3:Event {event: "Donate $2"}), | |
| (timeline:Timeline {name: "Kilgore's timeline"}), | |
| (sept:Month {name: "September"}),(oct:Month {name: "October"}), | |
| (d9:Day {name: '9th'}),(d3:Day {name: '3rd'}), | |
| (y2017:Year {name: '2017'}), | |
| (timeline)-[:TIMELINE_OF]->(kilgore), | |
| (timeline)-[:YEAR]->(y2017)-[:MONTH]->(sept)-[:DAY]->(d3)<-[:HAPPENED_ON]-(e1)-[:HAPPENED_WITH]->(kilgore), | |
| (timeline)-[:YEAR]->(y2017)-[:MONTH]->(sept)-[:DAY]->(d9)<-[:HAPPENED_ON]-(e2)-[:HAPPENED_WITH]->(kilgore), | |
| (timeline)-[:YEAR]->(y2017)-[:MONTH]->(oct)-[:DAY]->(d3)<-[:HAPPENED_ON]-(e3)-[:HAPPENED_WITH]->(kilgore); | |
| // so, modified according to the book | |
| create | |
| (logan:Person {name: "Logan"}), | |
| (ltl:Timeline {name: "Logan's timeline"}), | |
| (ltl)-[:TIMELINE_OF]->(logan), | |
| (kilgore:Person {name: "Kilgore"}), | |
| (ktl:Timeline {name: "Kilgore's timeline"}), | |
| (ktl)-[:TIMELINE_OF]->(kilgore); | |
| // and subsequent queries to add events | |
| match (timeline:Timeline {name: "Kilgore's timeline"})-[:TIMELINE_OF]->(kilgore) | |
| // this needs to be CREATE as each event is unique and | |
| // it would match to other people's events | |
| create (event:Event {event: "Napping"})-[:HAPPENED_WITH]->(kilgore) | |
| merge (timeline)-[:YEAR]->(year:Year {value: 2017}) | |
| merge (year)-[:MONTH]->(month:Month {value: 10, name: "October"}) | |
| merge (month)-[:DAY]->(day:Day {value: 3, name: "3rd"}) | |
| merge (day)<-[:HAPPENED_ON]-(event); | |
| match (timeline:Timeline {name: "Kilgore's timeline"})-[:TIMELINE_OF]->(kilgore) | |
| create (event:Event {event: "Something else"})-[:HAPPENED_WITH]->(kilgore) | |
| merge (timeline)-[:YEAR]->(year:Year {value: 2017}) | |
| // partial matches are ok later | |
| merge (year)-[:MONTH]->(month:Month {value: 10}) | |
| merge (month)-[:DAY]->(day:Day {value: 3}) | |
| merge (day)<-[:HAPPENED_ON]-(event); | |
| match (timeline:Timeline {name: "Kilgore's timeline"})-[:TIMELINE_OF]->(kilgore) | |
| create (event:Event {event: "Donate"})-[:HAPPENED_WITH]->(kilgore) | |
| merge (timeline)-[:YEAR]->(year:Year {value: 2017}) | |
| merge (year)-[:MONTH]->(month:Month {value: 9, name: "September"}) | |
| merge (month)-[:DAY]->(day:Day {value: 3, name: "3rd"}) | |
| merge (day)<-[:HAPPENED_ON]-(event); | |
| match (timeline:Timeline {name: "Kilgore's timeline"})-[:TIMELINE_OF]->(kilgore) | |
| create (event:Event {event: "study"})-[:HAPPENED_WITH]->(kilgore) | |
| merge (timeline)-[:YEAR]->(year:Year {value: 2017}) | |
| merge (year)-[:MONTH]->(month:Month {value: 9}) | |
| merge (month)-[:DAY]->(day:Day {value: 12, name: "12th"}) | |
| merge (day)<-[:HAPPENED_ON]-(event); | |
| // https://imgur.com/GcPkowr | |
| // adding entries to logan in the same way would create another date subtree for logan | |
| // only - so there would be one for logan AND one for kilgore | |
| // https://imgur.com/b2eSeYV | |
| // how could they be treated as unique? | |
| // anyhow, to query all the events for kilgore | |
| match path=(timeline:Timeline {name: "Kilgore's timeline"})-[:YEAR]->(:Year)-[:MONTH]->(:Month)-[:DAY]->(:Day)<-[:HAPPENED_ON]-(:Event)-[:HAPPENED_WITH]->(:Person {name: "Kilgore"}) return nodes(path); | |
| // (add screenshot) | |
| // try to add logan to the mix so that he uses the unique date parts | |
| match (timeline:Timeline {name: "Logan's timeline"})-[:TIMELINE_OF]->(logan), (year:Year {value: 2017}), (month:Month {value: 9}),(day:Day {value: 12, name: "12th"}) | |
| merge (timeline)-[:YEAR]->(year)-[:MONTH]->(month)-[:DAY]->(day)<-[:HAPPENED_ON]-(:Event {event: "slacking off"})-[:HAPPENED_WITH]->(logan); | |
| // this sort of works because of selecting the unique date parts explicitly | |
| // it won't add extra nodes but produces duplicate relationships. | |
| // https://imgur.com/avF1PNk | |
| // PROPOSED SOLUTION 1: match on the exact relationships as well and use them | |
| // PROPOSED SOLUTION 2: use multiple MERGE clauses | |
| // let's try #2 as it seems less messy | |
| match (timeline:Timeline {name: "Logan's timeline"})-[:TIMELINE_OF]->(logan), (year:Year {value: 2017}), (month:Month {value: 9}),(day:Day {value: 12, name: "12th"}) | |
| create (event:Event {event: "slacking off"})-[:HAPPENED_WITH]->(logan) | |
| merge (timeline)-[:YEAR]->(year) | |
| merge (year)-[:MONTH]->(month) | |
| merge (month)-[:DAY]->(day) | |
| merge (day)<-[:HAPPENED_ON]-(event); | |
| // It works: | |
| // https://imgur.com/tgP42t7 | |
| // let's see how the above query asking for kilgore's events holds up | |
| match path=(timeline:Timeline {name: "Kilgore's timeline"})-[:YEAR]->(:Year)-[:MONTH]->(:Month)-[:DAY]->(:Day)<-[:HAPPENED_ON]-(:Event)-[:HAPPENED_WITH]->(:Person {name: "Kilgore"}) return nodes(path); | |
| ╒══════════════════════════════════════════════════════════════════════╕ | |
| │"nodes(path)" │ | |
| ╞══════════════════════════════════════════════════════════════════════╡ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"12th","value":12},{"event":"study"},{"name":"Kilgore"}│ | |
| │] │ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"12th","value":12},{"event":"study"},{"name":"Kilgore"}│ | |
| │] │ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"3rd","value":3},{"event":"Donate"},{"name":"Kilgore"}]│ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"12th","value":12},{"event":"study"},{"name":"Kilgore"}│ | |
| │] │ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"12th","value":12},{"event":"study"},{"name":"Kilgore"}│ | |
| │] │ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"3rd","value":3},{"event":"Donate"},{"name":"Kilgore"}]│ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"October","value│ | |
| │":10},{"name":"3rd","value":3},{"event":"Something else"},{"name":"Kil│ | |
| │gore"}] │ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"October","value│ | |
| │":10},{"name":"3rd","value":3},{"event":"Napping"},{"name":"Kilgore"}]│ | |
| └──────────────────────────────────────────────────────────────────────┘ | |
| // we get 8 paths because of the relationship duplication on our first try, so we can either | |
| // ask for a DISTINCT result or clean up. | |
| match path=(timeline:Timeline {name: "Kilgore's timeline"})-[:YEAR]->(:Year)-[:MONTH]->(:Month)-[:DAY]->(:Day)<-[:HAPPENED_ON]-(:Event)-[:HAPPENED_WITH]->(:Person {name: "Kilgore"}) return distinct(nodes(path)); | |
| ╒══════════════════════════════════════════════════════════════════════╕ | |
| │"(nodes(path))" │ | |
| ╞══════════════════════════════════════════════════════════════════════╡ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"12th","value":12},{"event":"study"},{"name":"Kilgore"}│ | |
| │] │ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"September","val│ | |
| │ue":9},{"name":"3rd","value":3},{"event":"Donate"},{"name":"Kilgore"}]│ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"October","value│ | |
| │":10},{"name":"3rd","value":3},{"event":"Something else"},{"name":"Kil│ | |
| │gore"}] │ | |
| ├──────────────────────────────────────────────────────────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017},{"name":"October","value│ | |
| │":10},{"name":"3rd","value":3},{"event":"Napping"},{"name":"Kilgore"}]│ | |
| └──────────────────────────────────────────────────────────────────────┘ | |
| // how about kilgore? (using distinct still for the above reasons) | |
| match path=(timeline:Timeline {name: "Logan's timeline"})-[:YEAR]->(:Year)-[:MONTH]->(:Month)-[:DAY]->(:Day)<-[:HAPPENED_ON]-(:Event)-[:HAPPENED_WITH]->(:Person {name: "Logan"}) return distinct(nodes(path)); | |
| // let's clean up the extra edges | |
| // (these answers are worth a post by themselves: | |
| https://stackoverflow.com/questions/18202197/how-do-i-delete-duplicate-relationships-between-two-nodes-with-cypher | |
| https://stackoverflow.com/questions/32742751/what-is-the-difference-between-multiple-match-clauses-and-a-comma-in-a-cypher-qu | |
| // querying the duplicate edges with specifying the edges | |
| match (:Year {value: 2017})-[m:MONTH]->(month:Month {value: 9}) | |
| with collect(id(m)) as ms | |
| match (month)-[d:DAY]->(:Day {value: 12}) | |
| with ms, collect(id(d)) as ds | |
| return ms, ds; | |
| ms ds | |
| [213, 206] [214, 210] | |
| // !!! THIS JUST CHECKS WHETHER THERE ARE PARALLEL EDGES BETWEEN NODES BUT | |
| // !!! DOES NOT CARE FOR DIRECTION AND EDGE LABEL -> INCORPORATE THESE AS WELL | |
| // or more elegantly, querying duplicate edges in general: | |
| match (n)-[r]-(m) | |
| with n, m, collect(id(r)) as relationship_ids | |
| //return min(id(n),id(m)) as min, max(id(n),id(m)) as max, collect(id(r)) as relationship_ids; | |
| with | |
| case when id(n) > id(m) then [m,n] else [n,m] end as node_pairs, | |
| relationship_ids | |
| return distinct node_pairs, relationship_ids; | |
| ╒═══════════════════════════════════════════════════════════╤══════════════════╕ | |
| │"node_pairs" │"relationship_ids"│ | |
| ╞═══════════════════════════════════════════════════════════╪══════════════════╡ | |
| │[{"name":"Logan"},{"event":"slacking off"}] │[216] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"September","value":9},{"name":"12th","value":12}]│[214,210] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"event":"study"},{"name":"12th","value":12}] │[211] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"event":"Donate"},{"name":"3rd","value":3}] │[208] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"value":2017},{"name":"October","value":10}] │[200] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Kilgore"},{"event":"Something else"}] │[203] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Kilgore's timeline"},{"value":2017}] │[199] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Logan's timeline"},{"value":2017}] │[212] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"3rd","value":3},{"event":"Something else"}] │[204] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"12th","value":12},{"event":"slacking off"}] │[218] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"value":2017},{"name":"September","value":9}] │[213,206] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"event":"Napping"},{"name":"3rd","value":3}] │[202] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Kilgore"},{"event":"study"}] │[209] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Kilgore"},{"event":"Napping"}] │[198] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Logan"},{"event":"slacking off"}] │[217] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"12th","value":12},{"event":"slacking off"}] │[215] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Kilgore"},{"event":"Donate"}] │[205] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"September","value":9},{"name":"3rd","value":3}] │[207] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Logan"},{"name":"Logan's timeline"}] │[196] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"Kilgore"},{"name":"Kilgore's timeline"}] │[197] │ | |
| ├───────────────────────────────────────────────────────────┼──────────────────┤ | |
| │[{"name":"October","value":10},{"name":"3rd","value":3}] │[201] │ | |
| └───────────────────────────────────────────────────────────┴──────────────────┘ | |
| //TODO1: clean up duplicate edges using query and SO answer above | |
| //TODO2: add 3rd, 4th etc person and prove that treating date parts uniquely is sustainable | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment