В своем предыдущем посте в блоге я показал, как добавить новое свойство / поле к узлу с меткой / записью в таблице для набора данных футбольных передач, с которым я играл.
После введения этого свойства «национальности» я понял, что у меня теперь есть некоторое дублирование в модели:
Players.nationality и clubs.country ссылаются на одни и те же страны, но они оба хранят их в виде строк, поэтому мы не можем гарантировать целостность наших стран и гарантировать, что мы ссылаемся на одну и ту же страну.
У нас та же проблема в графической модели:
На этот раз Player.nationality и Club.country относятся к одним и тем же странам.
Мы можем решить нашу проблему, введя таблицу стран в реляционной модели и набор узлов с меткой «Страна» в графовой модели. Начнем с реляционного.
Это модель, к которой мы стремимся:
Первое, что нам нужно сделать, это создать таблицу стран и заполнить ее:
1
2
3
4
|
CREATE TABLE countries ( "code" CHARACTER VARYING (3) NOT NULL PRIMARY KEY , "name" CHARACTER VARYING (50) NOT NULL ); |
1
2
3
|
INSERT INTO countries VALUES ( 'MNE' , 'Montenegro' ); INSERT INTO countries VALUES ( 'SWZ' , 'Swaziland' , 'caf' ); ... |
Далее давайте обновим таблицу клубов для ссылки на таблицу стран:
1
2
3
|
ALTER TABLE clubs ADD COLUMN country_id CHARACTER VARYING (3) REFERENCES countries(code); |
И давайте запустим запрос для заполнения этого столбца:
1
2
3
4
5
6
|
UPDATE clubs AS cl SET country_id = c.code FROM clubs INNER JOIN countries AS c ON c. name = clubs.country WHERE cl.id = clubs.id; |
Этот запрос перебирает все клубы, запрашивает таблицу стран, чтобы найти идентификатор страны для этой строки, а затем сохраняет его в поле «country_id». Наконец, мы можем удалить поле «страна»:
1
2
|
ALTER TABLE clubs DROP COLUMN country; |
Теперь мы делаем то же самое упражнение для стола игроков:
1
2
3
|
ALTER TABLE players ADD COLUMN country_id CHARACTER VARYING (3) REFERENCES countries(code); |
1
2
3
4
5
6
|
UPDATE players AS p SET country_id = c.code FROM players INNER JOIN countries AS c ON c. name = players.nationality WHERE p.id = players.id; |
1
2
|
ALTER TABLE players DROP COLUMN nationality; |
Теперь пришло время для графика. Вот модель, к которой мы хотим добраться:
Сначала мы создадим страны:
1
2
|
CREATE CONSTRAINT ON (c:Country) ASSERT c.id IS UNIQUE |
1
2
3
4
|
LOAD CSV WITH HEADERS FROM "file:///countries.csv" AS row MERGE (country:Country {id: row.countryCode}) ON CREATE SET country. name = row.country |
А теперь давайте заставим клубы и игроков указывать на узлы этих стран и избавляться от их соответствующих свойств национальности / страны:
1
2
3
4
|
MATCH (club:Club) MATCH (country:Country { name : club.country}) MERGE (club)-[:PART_OF]->(country) REMOVE club.country |
1
2
3
4
|
MATCH (player:Player) MATCH (country:Country { name : player.nationality}) MERGE (player)-[:PLAYS_FOR]->(country) REMOVE player.nationality |
И это все, теперь мы можем писать запросы к нашей новой модели.
Ссылка: | Neo4j vs Relational: Рефакторинг — Извлечение узла / таблицы от нашего партнера по JCG Марка Нидхэма в блоге Марка Нидхэма . |