Графовая модель БД "Живопись на марках"
Графовую модель данной предметной области можно представить в виде показанной на рисунке схемы, где прямоугольниками представлены узлы, а стрелками ребра – связи между узлами. Тип связи указан надписью у ребра. Обратите внимание на связь «обучал», которую мы не реализовали в реляционной схеме данных. Это ребро связывает экземпляры одной и той же сущности – художник – отношением «учитель - ученик».
Для реализации этой модели будем использовать SQL Server, который в издании 2017 начал поддерживать графовую модель данных. В данной реализации узлы и связи представляются таблицами специального типа. Давайте создадим их в схеме Graph (о структуре этих таблиц можно почитать здесь).
Скрипт схемы графовой БД (SQL Server)
Следует обратить внимание, что таблицы ребер в данном случае вообще не имеют определяемых пользователем столбцов, хотя ничто не мешает вам при необходимости их создать.
Теперь нам нужны данные. Возьмем их из реляционной базы данных, которая уже обсуждалась ранее. (Здесь мы предполагаем, что реляционная структура реализована в той же самой базе данных SQL Server в схеме dbo).
/* Узлы */
INSERT INTO Graph.Museums(id, name, town)
SELECT id, name, town FROM dbo.Museums;
INSERT INTO Graph.Artists
SELECT a.id, a.name, birth, death, c.name country FROM dbo.Artists a
JOIN dbo.Countries c ON c.id=a.country_id;
INSERT INTO Graph.Paints(id,name,creation)
SELECT id,name, creation FROM dbo.Paints;
/* Связи */
INSERT INTO Graph.Has($from_id, $to_id)
SELECT gm.$node_id, gp.$node_id FROM Graph.Museums gm
JOIN dbo.Paints p ON gm.id = p.museum_id
JOIN Graph.Paints gp ON gp.id =p.id;
INSERT INTO Graph.Draws($from_id, $to_id)
SELECT am.$node_id, gp.$node_id FROM Graph.Artists am
JOIN dbo.Paints p ON am.id = p.artist_id
JOIN Graph.Paints gp ON gp.id =p.id;
Для третьей таблицы (Teaches), которая реализует связь «учитель – ученик», у нас нет данных в реляционной модели. Поэтому эти данные будем вносить вручную. Здесь мы приводим пару строк в качестве примера:
INSERT INTO Graph.Teaches($from_id, $to_id) VALUES
((SELECT $node_id FROM Graph.Artists WHERE id=212), (SELECT $node_id FROM Graph.Artists WHERE id=241)),
((SELECT $node_id FROM Graph.Artists WHERE id=88), (SELECT $node_id FROM Graph.Artists WHERE id=39));
Эти строки устанавливают связь между Рубо Ф.А. (учитель, id=212) и АВИЛОВЫМ М.И. (ученик, id=241), а также ПОЛЕНОВЫМ В.Д. (учитель, id=88) и АРХИПОВЫМ А.Е. (ученик, id=39).
Заметим, что поскольку граф в реализации SQL Server представляется таблицами, мы можем для извлечения данных из графовой базы использовать обычный синтаксис SQL-запросов. Однако для демонстрации новых возможностей я хочу использовать специальные средства, а именно, функцию MATCH, позволяющую создавать шаблоны для поиска узлов в стиле языка Cypher.
Примеры запросов к БД
1. Все пары учитель-ученик можно получить с помощью следующего запроса:
select teacher.name учитель ,pupil.name ученик
from graph.Teaches t, graph.Artists teacher, graph.artists Pupil
where match(teacher-(t)->pupil);
2. Найти учителя художника Кончаловского П.П. .
select teacher.name учитель
from graph.Teaches t, graph.Artists teacher, graph.artists Pupil
where match(teacher-(t)->pupil) and pupil.name like '%Кончаловский%';
учитель |
---|
САВИНСКИЙ В.Е. |
Предикат LIKE в предложении WHERE используется для того, чтобы выполнять поиск только по фамилии без учета инициалов.
3. Найти учеников художника Перова В.Г.
select pupil.name ученик
from graph.Teaches t,graph.Artists teacher,graph.artists Pupil
where match(teacher-(t)->pupil) and teacher.name like '%Перов%';
ученик |
---|
КАСАТКИН Н.А. |
ЛЕБЕДЕВ К.В. |
НЕСТЕРОВ М.В. |
РЯБУШКИН А.П. |
4. Найти учителя художника Нестерова.
select teacher0.name "учитель учителя", teacher.name учитель ,pupil.name ученик
from graph.Teaches t, graph.Teaches t0 ,graph.Artists teacher,graph.artists Pupil, graph.Artists teacher0
where match(teacher0-(t0)->teacher-(t)->pupil) and teacher.name like '%Нестеров%';
учитель учителя | учитель | ученик |
---|---|---|
ПЕРОВ В.Г. | НЕСТЕРОВ М.В. | БОГАТКИН В.В. |
5. Картины художника Шишкина, которые находятся в Русском музее.
select paint.name картина ,museum.name музей
from graph.Paints paint,graph.Artists artist,graph.museums museum,
graph.Has h, graph.draws d
where match(museum-(h)->paint<-(d)-artist)
and artist.name like '%Шишкин%' and museum.name like 'Русский%';
картина | музей |
---|---|
Дубы | Русский Музей (Мих.дв.) |
Корабельная роща | Русский Музей (Мих.дв.) |