# Мультимодельность
# Общие сведения
NitrosBase — мультимодельная СУБД, поддерживающая следующие модели данных:
- реляционная,
- графовая,
- документная.
К данным в каждой из моделей можно обращаться на наиболее естественном для нее языке. К реляционным — на SQL, к графовым — на Gremlin-подобном языке Graph-it и на SPARQL, к документным — на MongoDB query.
Все перечисленные модели равноправны и являются представлениями внутренней. Обращаться к внутренней модели напрямую возможно лишь через С++ API.
Все представления являются доступными для модификации: изменение данных в одном из них приводит к изменениям данных во внутренней модели и в других представлениях.
# Графовое представление
Наиболее естественно внутренняя модель отображается в графовую модель данных. В графовом представлении фрагмент данных демонстрационной базы будет выглядеть как на рисунке ниже.
Для запросов к графовому представлению возможно использовать языки SPARQL и Graph-it.
Запрос на SPARQL, возвращающий модель автомобиля, год его производства и имя владельца, будет выглядеть следующим образом:
SELECT * {
[] type car ;
model ?model ;
year ?year ;
owner [ name ?dname ] .
}
Язык Graph-it синтаксически схож с Gremlin:
g().v(car)
.in(type)
.get(model, year)
.out(owner).get(name)
.select(model, year, name)
Результат выполнения обоих запросов будет следующим:
+-------------+------+-------------+
| model | year | name |
+-------------+------+-------------+
| "Bugatti" | 2015 | "Brad" |
+-------------+------+-------------+
| "Mercedes" | 2014 | "Angelina" |
+-------------+------+-------------+
| "Mercedes" | 2014 | "Brad" |
+-------------+------+-------------+
| "Bentley" | 2016 | "Angelina" |
+-------------+------+-------------+
# Реляционное представление
В реляционной модели данные будут представлены как совокупность четырех таблиц.
Таблица «person»
id | name | lastname | age | city |
---|---|---|---|---|
"1234567801" | Brad | Pitt | 56 | Shawnee |
"1234567802" | Angelina | Jolie | 43 | Los Angeles |
Таблица «car»
id | model | year | color | number |
---|---|---|---|---|
"1234567803" | Bugatti | 2015 | blue | US 1234 |
"1234567804" | Mercedes | 2014 | black | US 4444 |
"1234567805" | Bentley | 2016 | red | US 4321 |
Таблица «owner»
fromid | toid |
---|---|
"1234567803" | "1234567001" |
"1234567804" | "1234567001" |
"1234567804" | "1234567002" |
"1234567805" | "1234567002" |
Таблица «friend»
fromid | toid |
---|---|
1234567801 | 1234567002 |
Запрос, возвращающий модель автомобиля, год его производства и имя владельца, на SQL будет выглядеть так:
SELECT с.model, с.year, p.name
FROM car с
JOIN owner o ON c.id = o.fromid
JOIN person p ON p.personid = o.toid
Кроме того, к таблице «car» можно обратиться так, как если бы она содержала столбец owner
, ссылающийся на записи непосредственно в таблице person
:
SELECT c.model, c.year, p.name
FROM car c
JOIN person p ON с.owner = p.id
Результат выполнения обоих запросов будет тем же, что и при обращении к графовой модели:
+-------------+------+-------------+
| model | year | name |
+-------------+------+-------------+
| "Bugatti" | 2015 | "Brad" |
+-------------+------+-------------+
| "Mercedes" | 2014 | "Angelina" |
+-------------+------+-------------+
| "Mercedes" | 2014 | "Brad" |
+-------------+------+-------------+
| "Bentley" | 2016 | "Angelina" |
+-------------+------+-------------+
# JSON-представление
В документном представлении будут созданы две коллекции: «car» и «person».
Коллекция «person» (2 документа)
{
"id" : "1234567801",
"type" : "person",
"name" : "Brad",
"lastname" : "Pitt",
"age" : 56,
"city" : "Shawnee"
"friend" : [ { "id" : "1234567802" } ]
}
{
"id" : "1234567802",
"type" : "person",
"name" : "Angelina",
"lastname" : "Jolie",
"age" : 43,
"city" : "Los Angeles"
}
Коллекция «car» (3 документа)
{
"id" : "1234567803",
"type" : "car",
"model" : "Bugatti",
"color" : "blue",
"year" : 2015,
"number" : "US 1234",
"owner": [ { "id" : "1234567801" } ]
}
{
"id" : "1234567804",
"type" : "car",
"model" : "Mercedes",
"color" : "black",
"year" : 2014,
"number" : "US 4444",
"owner": [ { "id" : "1234567801" }, { "id" : "1234567802" } ]
}
{
"id" : "1234567805",
"type" : "car",
"model" : "Bentley",
"color" : "blue",
"year" : 2015,
"number" : "US 1234",
"owner": [ { "id" : "1234567801" }, { "id" : "1234567802" } ]
}
С помощью специальных техник, в этом документе не рассматриваемых, можно добиться того, чтобы одни документы включались в другие не «по ссылке», а по «значению» (были бы «embedded», «внедренными»).
# Правила формирования представлений
# Соответствие реляционной модели и внутренней модели
- Любая запись любой таблицы реляционной модели — это запись внутренней модели.
- Название таблицы — это тип записи во внутренней модели. Если во внутренней модели запись имеет несколько типов, в реляционной она присутствует в нескольких таблицах.
- Название столбца таблицы — это название поля записи во внутренней модели, а значение в столбце таблицы — это значение соответствующего поля записи. В частности, значением в столбце
id
является идентификатор записи. - Записи внутренней модели, имеющие один и тот же тип, могут иметь различный состав полей. Состав столбцов в таблице, соответствующей типу, будет соответствовать объединенному составу полей всех записей. При отсутствии у записи внутренней модели того или иного поля в соответствующем столбце таблицы будет
NULL
. - Одноименные поля записей внутренней модели могут иметь различные скалярные типы. Настройками СУБД может быть обеспечено создание отдельного столбца для каждого типа или же специального столбца «переменного» типа.
- Связям между записями соответствуют промежуточные таблицы. Дополнительно в таблице, соответствующей источнику связи, создаются столбцы — внешние ключи со специальным поведением в операциях соединения (
JOIN
): если связь множественная, внешний ключ адресует одновременно несколько записей в опорном столбце.
# Соответствие документной модели и внутренней модели
- Документ соответствует записи внутренней модели, поля документа соответствуют полям записи. В частности, идентификатор документа (
id
) – это идентификатор записи внутренней модели. - Связи внутренней модели по умолчанию представляются как одноименные связям поля. Значениям полей являются массивы со значениями
id
документов, соответствующих связанным записям. - Коллекцию документов образуют документы, соответствующие записям, имеющим один и тот же тип (
type
). Один документ может находиться в нескольких коллекциях.