В своем предыдущем посте в блоге я показал, как добавить новое свойство / поле к узлу с меткой / записью в таблице для набора данных футбольных передач, с которым я играл.
После введения этого свойства «национальности» я понял, что у меня теперь есть некоторое дублирование в модели:
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 clubsADD COLUMN country_id CHARACTER VARYING(3)REFERENCES countries(code); |
И давайте запустим запрос для заполнения этого столбца:
|
1
2
3
4
5
6
|
UPDATE clubs AS clSET country_id = c.codeFROM clubsINNER JOIN countries AS c ON c.name = clubs.countryWHERE cl.id = clubs.id; |
Этот запрос перебирает все клубы, запрашивает таблицу стран, чтобы найти идентификатор страны для этой строки, а затем сохраняет его в поле «country_id». Наконец, мы можем удалить поле «страна»:
|
1
2
|
ALTER TABLE clubsDROP COLUMN country; |
Теперь мы делаем то же самое упражнение для стола игроков:
|
1
2
3
|
ALTER TABLE playersADD COLUMN country_id CHARACTER VARYING(3)REFERENCES countries(code); |
|
1
2
3
4
5
6
|
UPDATE players AS pSET country_id = c.codeFROM playersINNER JOIN countries AS c ON c.name = players.nationalityWHERE p.id = players.id; |
|
1
2
|
ALTER TABLE playersDROP 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 rowMERGE (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 Марка Нидхэма в блоге Марка Нидхэма . |



