# Мультимодельность

# Общие сведения

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). Один документ может находиться в нескольких коллекциях.