CPhoto by shen liu on Unsplash

Simple example of N-ary relationship to understand basics of Neo4j Graph Data Modeling

May 13: Formula 1, One Month Graph Challenge

Vlad Batushkov
4 min readMay 13, 2019

--

Welcome word

In this series of small posts I do one simple graph daily. Domain model of graph somehow related to day’s history, some historical event, celebration or person. I do this challenge to learn Neo4j Data Modeling and Cypher. Every day. One month. Follow me. Maybe you will be inspired and next month would be yours One Month Graph Challenge. #OMGChallenge

Domain model

This day 69 years ago in Silverstone, England, the first race of the first Formula 1 championship took a place. And so far Formula 1 is one of the most spectacular events in the world. I remember my first childhood TV sessions when I watching Schumacher victories in Benetton team.

Today I want to analyse results of whole history of Formula 1 competition and find the best of the best pilots ever.

Let’s think a little bit about how to organize our graph. How to say that a particular pilot in a particular year won in a particular country? In the graph database language it is mean: you should to take a year node, take a country node, take a pilot node and connect them together — to get a winner node. So, winner is N-ary relationship node based on other 3 nodes. Here is the result schema:

Graph

Parse data results of Formula 1 from official website:

Winner is an aggregation root, it can includes all necessary information of these 3 nodes, so I put all three properties inside winner. Now I can say that pilot, country and year is kind of normalized nodes, while winner is kind of denormalized node. I can read only winner nodes to know everything around. Very useful for reading purposes.

One thing to add here. I got unexpected result from apoc.load.html with 2 projections. By documentation output must be a Map type with of this structure:

A: { name: <list of elements>, name2: <list of elements> }

But unfortunately, I got result of this structure:

B: [ { name: <list of elements> }, { name2: <list of elements> } ]

So, I wrote this 2 magic lines to transform A into B:

WITH collect(value) as data
WITH { pilots: data[0].pilot, places: data[1].place } as root

Now let’s find the best of the best. A person with the most victories in all history of Formula 1:

For sure, Michael Schumacher! I didn’t expect another answer. But as you can see Hamilton can do a history very soon. Write a query for this was very easy. And if you want to find the best pilots for each concrete races, it is also super simple:

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Vlad Batushkov
Vlad Batushkov

Written by Vlad Batushkov

Engineering Manager @ Agoda. Neo4j Ninja. Articles brewed on modern tech, hops and indie rock’n’roll.

No responses yet

Write a response