Как я упоминал в предыдущем посте, я играл с некоторыми футбольными данными за последние несколько дней, и один из моих запросов (с использованием шифра ) состоял в том, чтобы найти всех игроков, которых отправили в этом сезоне в Премьер-лигу.
Модель на графике отсылок выглядит следующим образом:
Мой начальный запрос выглядел так:
START player = node:players('name:*') MATCH player-[:sent_off_in]-game-[:in_month]-month RETURN player.name, month.name
Сначала мы получаем имена всех игроков, которые хранятся в индексе, а затем следим за отношениями с играми, в которые они были отправлены, а затем выясняем, в какие месяцы были сыграны эти игры.
Этот запрос возвращает:
+----------------------------+ | player.name | month.name | +----------------------------+ | "Jenkinson" | "February" | | "Chico" | "September" | | "Odemwingie" | "September" | | "Agger" | "August" | | "Cole" | "December" | | "Whitehead" | "August" | ... +----------------------------+
Я подумал, что было бы интересно посмотреть, сколько отправок было в каждом месяце, чего мы добились в SQL, используя GROUP BY.
Cypher имеет множество функций агрегации, которые позволяют нам достичь того же результата.
В нашем случае мы хотим использовать функцию COUNT и хотим, чтобы нашим ключом группировки был месяц года, поэтому мы должны включить его и в нашу инструкцию RETURN:
START player = node:players('name:*') MATCH player-[:sent_off_in]-game-[:in_month]-month RETURN COUNT(player.name) AS numberOfReds, month.name ORDER BY numberOfReds DESC
который возвращает:
+----------------------------+ | numberOfReds | month.name | +----------------------------+ | 7 | "October" | | 6 | "December" | | 4 | "September" | | 4 | "November" | | 3 | "August" | | 2 | "January" | | 2 | "February" | +----------------------------+
Насколько я могу судить, все, что не является агрегатной функцией, используется как часть ключа группировки, что означает, что мы можем включить более одного поля в наш ключ группировки.
Это не особенно актуально для нас для этого конкретного запроса, но было бы полезно, если бы мы добавили команды, за которые играют игроки.
Я расширил график, включив в него статистику игрока для каждой игры, которая также включает отношения, указывающие, за какую команду они играли в конкретной игре.
Модель теперь выглядит так:
Теперь это выглядит немного сложнее, но это был лучший способ, который я мог придумать для моделирования конкретных деталей игрока для матча.
Я не видел другого способа моделирования того факта, что игрок играл за определенную команду в матче, который я хочу использовать для некоторых других запросов, но если вы можете увидеть более простой способ, пожалуйста, дайте мне знать.
Чтобы получить список красных карточек и название команды, за которую играл нарушитель, мы можем написать следующий запрос:
START player = node:players('name:*') MATCH player-[:sent_off_in]-game-[:in_month]-month, game-[:in_match]-stats-[:stats]-player, stats-[:played_for]-team RETURN player.name, month.name, team.name ORDER BY month.name
Исходный запрос проходил путь от игрока к играм, в которые они были отправлены, а затем от игр к месяцу, в который игра проводилась.
Теперь мы добавили обход из игры в игровую статистику для этого игрока, а также перешли от игровой статистики к командному узлу, за который игрок играл в этой игре.
Когда мы запускаем это, мы получаем следующие результаты:
+--------------------------------------------+ | player.name | month.name | team.name | +--------------------------------------------+ | "Agger" | "August" | "Liverpool" | | "Whitehead" | "August" | "Stoke" | ... | "Shotton" | "December" | "Stoke" | | "Nzonzi" | "December" | "Stoke" | | "Jenkinson" | "February" | "Arsenal" | ... | "Ivanovic" | "October" | "Chelsea" | | "Torres" | "October" | "Chelsea" | +--------------------------------------------+
Итак, мы видим, что в декабре «Сток» отправил 2 игроков, а в октябре — «Челси».
Мы можем написать следующий запрос, чтобы вернуть набор результатов, который использует команду и месяц в качестве ключа группировки, то есть мы подсчитываем, сколько существует путей с одинаковой командой и месяцем:
START player = node:players('name:*') MATCH player-[:sent_off_in]-game-[:in_month]-month, game-[:in_match]-stats-[:stats]-player, stats-[:played_for]-team RETURN month.name, team.name, COUNT(player.name) AS numberOfReds ORDER BY numberOfReds DESC
Когда мы запускаем этот запрос, мы видим следующие результаты:
+--------------------------------------------+ | month.name | team.name | numberOfReds | +--------------------------------------------+ | "December" | "Stoke" | 2 | | "October" | "Chelsea" | 2 | ... | "August" | "Stoke" | 1 | | "November" | "Tottenham" | 1 | | "December" | "Everton" | 1 | +--------------------------------------------+
Все это более подробно объясняется в документации, но я подумал, что было бы интересно написать об этом с точки зрения того, кто более привык писать SQL и пытаться понять, как добиться того же в шифре.