AgensGraph

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 12:31, 13 марта 2019.
AgensGraph
AG logo.png
Разработчики: Bitnine Global Inc.
Выпущена: 2016
Постоянный выпуск: 2.0 / сентябрь 2018 г.
Состояние разработки: активноe
Написана на: C
Операционная система:

Linux

OS X

Windows
Локализация: Английский язык
Тип ПО: База Данных
Лицензия:

Creative Commons 3.0 License[Источник 1] [Ссылка] Creative Commons — Attribution-ShareAlike 3.0 Unported — CC BY-SA 3.0

http://creativecommons.org/licenses/by-sa/3.0/
Веб-сайт bitnine.net

AgensGraph - это база данных с множеством моделей нового поколения для современной комплексной среды данных. AgensGraph представляет собой многомодельную базу данных на основе СУБД PostgreSQL и поддерживает как реляционные, так и графические данные, одновременно. Это позволяет разработчикам интегрировать устаревшую реляционную модель данных и лексический граф данных в одной базе данных. AgensGraph поддерживает Ansi-SQL и Open Cypher[Источник 2]. SQL запросы и запросы Cypher могут быть интегрированы в один запрос в AgensGraph. AgensGraph является очень надежным, полнофункциональным и готовым к использованию на предприятии. Он оптимизирован для обработки сложных и предоставляет множество мощных функций базы данных, необходимых для среды базы данных предприятия, включая транзакции ACID, управление параллелизмом с несколькими версиями, хранимую процедуру, триггеры, ограничения, сложный мониторинг и лексическую модель данных (JSON). Кроме того, AgensGraph использует богатые экосистемы PostgreSQL и может быть расширен многими выдающимися внешними модулями, такими как PostGIS[Источник 3].

Особенности

  • Поддержка нескольких моделей модели данных графа свойств, модели реляционных данных и документов JSON
  • Поддержка языка запросов Cypher
  • Интегрированный запрос с использованием SQL и Cypher
  • Управление объектами графических данных
  • Иерархическая организация меток графа
  • Индексы свойств на обеих вершинах и ребрах
  • Ограничения: уникальные, обязательные и контрольные ограничения
  • ACID-транзакции
  • Подключение Hadoop
  • Репликация Active-standby
  • И многие другие функции

[Источник 4]

Модель данных

AgensGraph является многомодельной базой данных, а также представляет собой как модель графа свойств, так и реляционную модель.

Модель графа свойств

Рисунок 1 - Модель графа свойств с метками

Модель графа свойств содержит связанные объекты, которые могут иметь любое количество атрибутов. В AgensGraph объекты являются вершинами графа. Вершины могут иметь произвольное количество атрибутов и могут быть классифицированы с помощью меток. Метки используются для группировки вершин для представления некоторых категорий вершин; т.е. представляя персональную роль. Грани - это направленные соединения между двумя вершинами. Грани также могут иметь атрибуты и классифицированные метки, такие как вершины. В AgensGraph грань всегда имеет начальную вершину и конечную вершину(см. рис. 1). Если запрос пытается удалить вершину, он должен удалить все его грани. Сломанные грани не могут существовать в AgensGraph. Свойства ребер и вершин представлены в формате JSON. JSON - это текстовый формат для сериализации структурированных данные. JSON-пакеты состоят из шести типов данных: строк, чисел, логических, нулевых, объектов и массивов. Объекты AgensGraph полностью используют формат JSON, сохраняя информацию как неупорядоченные коллекции нулевого или больше пар имя / значение. Имя - это строка, а значением может быть любой вышеупомянутый тип, включая вложенный JSONтипы. AgensGraph специфически использует формат JSONB. Поскольку JSONB является разложенным двоичным форматом, он обрабатывается намного быстрее, чем обычный JSON, но за счет немного более медленного времени ввода.

Объекты данных в AgensGraph

Рисунок 2 - Простая модель данных AgensGraph

В AgensGraph можно создать несколько баз данных, и каждая база данных может содержать одну или несколько схем и графов. Схемы для реляционных таблиц, а объекты графа - для данных графа. Имя схемы и имя графа не могут одинаковыми. Вершины и ребра сгруппированы в метки. Существует два типа меток: метки вершин и метки грани. Пользователь может создавать несколько графов в базе данных, но только один граф может быть использован за один раз.[Источник 5](см. рис. 2).

Установка AgensGraph

sudo apt-get update

Для установки AgensGraph доступно два метода: загрузка двоичного пакета или компиляция пакета из исходного кода.

Установка AgensGraph в Linux

  1. Получить предварительно скомпилированный бинарный файл: посетите страницу загрузки AgensGraph и загрузите соответствующую версию AgensGraph.
  2. Извлечь пакет: извлеките загруженный файл в каталог для вашего использования (например, /usr/local/AgensGraph/ в Linux)
tar xvf /path/to/your/use

Установка сборка и установка из исходного кода

1. Получите доступ к gensub AgensGraph и получите исходный код

git clone https://github.com/bitnine-oss/agensgraph.git

2. Установите следующие необходимые библиотеки в соответствии с дистрибутивом Вашей ОС. 2.1 CentOS

yum install gcc glibc glib-common readline readline-devel zlib zlib-devel flex bison 

2.2 Fedora

dnf install gcc glibc bison flex readline-readline-devel zlib zlib-devel

2.3 Ubuntu

sudo apt-get install build-essential libreadline-dev zlib1g-dev flex bison

3. Перейдите в папку с клоном и запустите configure в дереве исходных текстов.

./configure

4. Запустите сборку.

make install

5. Установите модуль расширения и бинарный

make install-world

Настройка после установки

1. Настройка временной среды (необязательно):

export LD_LIBRARY_PATH=/usr/local/AgensGraph/lib:$LD_LIBRARY_PATH
export PATH=/usr/local/AgensGraph/bin:$PATH
export AGDATA=/path/to/make/db_cluster

2. Создание кластера базы данных:

initdb [-D /path/to/make/db_cluster]

3. Запуск сервера:

ag_ctl start [-D /path/created/by/initdb]

4. Создание базы данных:

createdb [dbname]

Если dbname не указано, по умолчанию создается база данных с тем же именем, что и у текущего пользователя.

5. Выполните интерактивный терминал:

agens [dbname]

Если каталог db_cluster не указан с параметром -D, используется переменная окружения AGDATA.

Настройка параметров сервера

Для достижения оптимальной производительности очень важно правильно настроить параметры сервера в соответствии с размером данных и ресурсами компьютера. Среди многих параметров сервера следующие параметры имеют решающее значение для производительности запросов к графику AgensGraph. (Вы можете отредактировать файл $AGDATA/postgresql.conf чтобы установить эти параметры (требуется перезагрузка)).

  • shared_buffers: размер памяти для кэширования объектов данных. Этот параметр должен быть увеличен для производственной среды. Оптимален, когда он равен размеру данных. Но этот параметр должен быть установлен с учетом одновременных сеансов и объема памяти, выделенного для каждого запроса. Рекомендуемая настройка - половина объема физической памяти.
  • work_mem: это значение также должно быть увеличено в зависимости от объема физической памяти и свойств запросов, которые будут тщательно выполняться.
  • random_page_cost: этот параметр предназначен для оптимизации запросов. Для запросов к графику рекомендуется уменьшить это значение до 1 или 0,005 (в случае, если данные графика полностью кэшируются в памяти).

Для получения дополнительной информации вы можете обратиться к документации PostgreSQL. [Источник 6]

Метки

Рисунок 3 - Пример наследования меток грани

Метки используются для группировки вершин и ребер. Пользователи могут создавать индексы свойств для всех вершин под данной меткой. Метки могут использоваться для предоставления элементов управления доступом для разных типов пользователей, а иерархия меток может быть создана для добавления наследование меток. Для вершин есть метки по умолчанию: ag_vertex. Если создать вершину без указания ее метки, то вершина сохраняется в метке по умолчанию. В то время как грань всегда имеет одну метку. Принято называть вершинную метку и метку грани как VLABEL и ELABEL соответственно.

  • VLABEL: метка вершины. Классифицирует вершины для представления своих ролей.
- Vertex: объекты, которые могут содержать атрибуты.
  • ELABEL: красная метка. Классифицирует ребра для представления своих ролей.
- Edge: отношения, связывающие объекты.

Каждая метка наследует одну или несколько меток. На рисунке 3 показана примерная иерархия красных меток. Иерархия меток похожа на иерархию классов в объектно-ориентированном программировании. Каждая родительская метка содержит данные дочерних меток. К примеру, учитывая указанную выше иерархию, если запрос совпадает с гранью "друзья", тогда результаты содержат данные метки "соседей по комнате". [Источник 5]

Язык описания данных

Создание Графа

Чтобы создать граф, необходимо использовать команду CREATE GRAPH.

CREATE GRAPH graphname;

В базе данных могут быть созданы несколько графиков. Чтобы указать, какой граф следует использовать, параметр сеанса используется метод graph_path . Чтобы показать текущий путь графика, используйте следующую команду.

SHOW graph_path;

Когда граф создается с использованием CREATE GRAPH, путь graph_path устанавливается в созданный граф, если параметр graph_path не установлен. Возможно создать несколько графов и изменить график graph_path на другой граф, используя следующую команду:

SET graph_path = filename; 

graph_path является переменной сеанса, поэтому каждый клиент должен установить graph_path перед тем запрашивая график. Только одно имя графа может быть указано для пути graph_path. Запросить несколько графов нельзя. Если вы задаете путь graph_path для каждого пользователя или базы данных с помощью инструкции ALTER ROLE или DATABASE, вам не нужно запускайте инструкцию SET graph_path всякий раз, когда вы подключаете базу данных.

ALTER ROLE user1 IN DATABASE gdb SET graph_path graph_name;
ALTER DATABASE gdb SET graph_path graph_name;

Удаление графа

DROP GRAPH graph_name CASCADE;

Граф имеет начальные метки для вершин и ребер. Эти метки нельзя удалить. Чтобы удалить граф, пользователи должны это сделать с опцией CASCADE. Если текущий graph_path - это удаленный граф, тогда путь graph_path сбрасывается до нуля.

Создание метки

CREATE VLABEL;
CREATE VLABEL friend inherits (person);
CREATE ELABEL knows;
CREATE ELABEL live_together;
CREATE ELABEL room_mate inherits (knows, live_together);

Ключевые слова VLABEL и ELABEL используются для идентификации вершин и ребер соответственно. CREATE VLABEL будет создайте метку вершины. VLABEL может наследовать только VLABEL(другими словами, VLABELне может наследовать ELABEL). Наследование в рамках AgensGraph - это возможность наследовать родительскую метку. Если не указано, система устанавливает исходную метку в качестве родительской метки. Несколько возможно создание сложных меток:

Удаление метки

DROP VLABEL friend;
DROP VLABEL person;

VLABEL friend наследует person, поэтому VLABEL person не может быть удален напрямую. VLABEL friend должен быть удален первым. Если метка привязана к любой вершине или ребру, вы не можете удалить эту метку, используя DROP VLABEL или DROP ELABEL.

DROP VLABEL person;
ERROR: cannot drop person because it is not empty.

Следует использовать DROP ... CASCADE для удаления метки независимо от того, связана она или нет, и в этом случае все данные объект, у которого эта метка удалена вместе с ней.

DROP VLABEL person CASCADE;
NOTICE: drop cascades to vlabel friend
DROP VLABEL
DROP ELABEL knows CASCADE;

[Источник 7]

Запросы AgensGraph

Запрос графа

Чтобы получать и обрабатывать данные графа, AgensGraph поддерживает язык запросов Cypher. Cypher является декларативным язык, похожий на SQL. Cypher легко учится, поскольку его синтаксис визуально описывает шаблоны, найденные на графиках. В этом руководстве объясняется, как писать запросы Cypher с помощью примерного графика. AgensGraph может хранить несколько графиков в одной базе данных. Тем не менее, Cypher не может различать несколько графиков. Поэтому AgensGraph поддерживает дополнительные языки описания данных для создания и управления графиками используя Cypher. Следующие операторы создают граф, называемый сетью, и устанавливают его как текущий граф.

CREATE GRAPH network;
SET graph_path = network;

В этом примере переменная graph_path явно задана в network. Однако, если параметр graph_path не задан перед созданием график, он будет установлен автоматически после создания графика.

Создание меток

Прежде чем создавать данные графа, генерация метки является базовой. Хотя это значение по умолчанию, метка генерируется автоматически когда вы указываете метку в операторе CREATE в Сypher (возможно создание VLABEL / ELABEL). Примечание: Будьте осторожны, чтобы не путать метку с листом. Новые метки могут быть созданы. Все элементы графа имеют одну метку. Для вершины, если метка не указана, используйте ag_vertex как метку по умолчанию. Для грани, метку нельзя опустить, метка ag_edge также существует, но используется для других целей. AgensGraph поддерживает DDL для создания таких меток. Следующие инструкции создают метки вершин человека и метки грани:

CREATE VLABEL person;
CREATE ELABEL knows;
CREATE (n:movie {title:'Matrix'});

Создание вершин и граней

Теперь мы можем создать вершины для персоны и грани, чтобы знать, используя предложение CREATE Cypher. Предложение CREATE создает шаблон, состоящий из вершин и ребер. Вершина имеет следующий вид: (variable: label {property: value, ...}), а ребро имеет: - [variable: label {property: value, ...}] -. Дополнительно < с левой стороны или > с правой стороны используется для обозначения направления ребра. Переменная может быть опущена, если созданные вершины и кромки не должны ссылаться. Примечание: AgensGraph не поддерживает -- грамматику для грани в шаблоне, потому что -- означает комментарий в конце строки. Следующие операторы создают три простых шаблона: "Tom knows Summer", "Pat knows Nikki" и "Olive knows Todd:

CREATE (:person {name: 'Tom'})-[:knows {fromdate:'2011-11-24'}]->(:person {name: 'Summer'});
CREATE (:person {name: 'Pat'})-[:knows {fromdate:'2013-12-25'}]->(:person {name: 'Nikki'});
CREATE (:person {name: 'Olive'})-[:knows {fromdate:'2015-01-26'}]->(:person {name: 'Todd'});
MATCH (p:Person {name: 'Tom'}),(k:Person{name: 'Pat'})
CREATE (p)-[:KNOWS {fromdate:'2017-02-27'} ]->(k);

Для сохранения свойств вершин и ребер, AgensGraph использует JSONB типа PostgreSQL. Свойства могут иметь вложенный JSONобъектов в качестве их значений. Поскольку AgensGraph использует систему типов PostgreSQL, любой тип данных, поддерживаемый PostgreSQL, может сохраняются в свойствах вершин и ребер.

Запрос графа

Используем шаблон, который мы создали выше. Cypher имеет предложение MATCH, чтобы указать шаблон в графе. Следующее утверждение описывает шаблон: "A person called Tom knows a person.

MATCH (n:person {name: 'Tom'})-[:knows]->(m:person) RETURN n.name AS n, m.name AS m;
n | m
-------+----------
"Tom" | "Summer"
"Tom" | "Pat"
(2 rows)

Поскольку свойства имеют тип jsonb , нам нужны методы для доступа к их значениям свойств. PostgreSQL поддерживает эти методы с помощью таких операторов, как "->", "- >>", "#>" и "# >>". Если пользователь хочет получить доступ к имени свойства вершинных m, можно написать "(m) - >> name". AgensGraph предлагает альтернативный способ доступа к этим элементам. AgensGraph использует оператор точку и операторы скобок "[]" для вершин и ребер для доступа к значениям свойств в объектах и ​​элементах в JSON, как показано выше. Предложение RETURN возвращает переменные и его свойства в результате запроса. Результатом является таблица, сопоставляемые шаблоны в строках.

Грани переменной длины

Рассмотрим запрос, который знает о «Tom» и знает о нем. Мы можем использовать предложение UNION:

MATCH (p:person {name: 'Tom'})-[:knows]->(f:person)
RETURN f.name
UNION ALL
MATCH (p:person {name: 'Tom'})-[:knows]->()-[:knows]->(f:person)
RETURN f.name;

Его также можно записать в виде:

MATCH (p:person {name: 'Tom'})-[r:knows*1..2]->(f:person)
RETURN f.name, r[1].fromdate;

Запрос в поисках вершин, расположенных после переменной длины путей вершины-вершины, типичен в базах данных графа. *1..2 используемый в грани, представляет такой грани переменной длины. Где 1 - минимальная длина ребра, а 2 - максимальная длина. Если вы не укажете значение, значения диапазона по умолчанию равны 1 и во внутреннем пространстве. Вы также можете использовать предложения обновления, такие как CREATE, SET, REMOVE, DELETE после предложений MATCH.

Управление графом

Вы можете установить свойства для вершин и ребер, используя предложение SET. Если вы установите значение null для свойства, свойство будут удалены. Следующий оператор индексирует данный шаблон и обновляет свойство в совпадающем ребро.

MATCH (:person {name: 'Tom'})-[r:knows]->(:person {name: 'Summer'})
SET r.since = '2009-01-08';

Чтобы удалить вершины и ребра в графе, мы можем использовать предложение DELETE. Следующий оператор отображает вершину и удаляет ее.

MATCH (n:person {name: 'Pat'}) DETACH DELETE (n);

Одинаковая форма network-графиков выглядит следующим образом:

MATCH (n)-[r]->(m) RETURN n.name AS n, properties(r) AS r, m.name AS m;
n | r | m
 ---------+---------------------------------------------------+---------- 
"Tom" | {"since": "2009-01-08", "fromdate": "2011-11-24"} | "Summer"
"Olive" | {"fromdate": "2015-01-26"} | "Todd"
<code>(2 rows)

Слияние

Если вам нужно убедиться, что шаблон существует на графе, вы можете использовать MERGE. Он попытается указать шаблон, если шаблон существует в графе, иначе он создает шаблон, если он не существует. Если шаблон существует, он рассматривается как MATCH , иначе оно рассматривается как предложение CREATE. MERGE - это MATCH или CREATE всего шаблона. Это означает, что если какой-либо элемент шаблона не существует, AgensGraph создаст весь шаблон. Следующее утверждение гарантирует, что каждый город существует на графике.

CREATE VLABEL customer;
CREATE VLABEL city;
CREATE (:customer {name:'Tom', city:'santa clara'}),
(:customer {name:'Summer ', city:'san jose'}),
(:customer {name:'Pat', city:'santa clara'}),
(:customer {name:'Nikki', city:'san jose'}),
(:customer {name:'Olive', city:'san francisco'});
MATCH (a:customer)
MERGE (c:city {name:a.city});
MATCH (c:city) RETURN properties(c);
properties
 ------------------------- 
{"name": "santa clara"}
{"name": "san jose"}
{"name": "san francisco"}
(3 rows)

MERGE может выполнять SET в зависимости от того, является ли шаблон MATCHED или CREATED. Если он был MATCH-ed, он выполнит ON MATCH SET. Если он был CREATE-ed, он выполнит предложение ON CREATE SET.

CREATE (:customer {name:'Todd', city:'palo alto'});
MATCH (a:customer)
MERGE (c:city {name:a.city})
ON MATCH SET c.matched = 'true'
ON CREATE SET c.created = 'true';
MATCH (c:city) RETURN properties(c);
properties
---------------------------------------------- 
{"name": "santa clara", "matched": "true"}
{"name": "san jose", "matched": "true"}
{"name": "san francisco", "matched": "true"}
{"name": "palo alto", "created": "true"}
(4 rows)

Уровень изоляции по умолчанию для транзакции - это Чтение, совершенное на AgensGraph. Поэтому, если другая транзакция одновременно выполняет MERGE для одного и того же шаблона, два (или более) одинаковых шаблона могут быть созданы в то же время время. Чтобы этого избежать, вы можете выполнить транзакцию на уровне сериализации, как в приведенном ниже примере. Если предпринимается попытка создать один и тот же шаблон одновременно, одна транзакция завершится с ошибкой. Если вы повторите попытку транзакции, он будет вести себя как MATCH вместо CREATE из-за шаблона, созданного с помощью транзакции уже существует.

BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
MATCH (a:customer)
MERGE (c:city {name:a.city});
COMMIT;

Поиск кратчайшего пути

Функция shortestpath может использоваться для кратчайшего пути между двумя вершинами. Если вы хотите указать все пути, вы можете использовать функцию allshortestpaths.

MATCH (p:person {name:'Tom'}), (f:person {name:'Olive'}) CREATE (p)-[:knows]->(f);
MATCH (p1:person {name: 'Tom'}), (p2:person {name: 'Todd'}),
path=shortestpath((p1)-[:knows*1..5]->(p2)) RETURN path;

В этом примере мы создаем путь "know" edge от "Tom" до "Pat". Чтобы указать путь "know" от "Tom" до "Nikki", мы может использовать функцию shortestpath. Функция shortestpath принимает шаблон, состоящий из начальной вершины, ребра и конечную вершину. Мы можем использовать выражение края переменной длины в краю, чтобы указать, если мы ищем определенный степень подключения. Результаты запроса следующие.

[person[3.1]{"name": "Tom"},knows[4.5][3.1,3.5]{},person[3.5]{"name": "Olive"},knows[4.3][3.5,3.6]
{"fromdate": "2015-01-26"},person[3.6]{"name": "Todd"}]

Гибридный запрос

В этом разделе мы увидим, как использовать SQL и Cypher вместе в AgensGraph, используя следующий примерный график. Hybrid Query выполняет агрегирование и статистическую обработку таблицы и столбца с использованием SQL-запроса, используемого в RDB, и запрос Cypher, используемый GDB, поддерживает лучший запрос данных, чем операция объединения RDB.

CREATE GRAPH bitnine;
CREATE VLABEL dev;
CREATE (:dev {name: 'someone', year: 2015});
CREATE (:dev {name: 'somebody', year: 2016});
CREATE TABLE history (year, event)
AS VALUES (1996, 'PostgreSQL'), (2016, 'AgensGraph');

Cypher в SQL

Поскольку результат запроса Cypher является отношением, вы можете использовать запрос Cypher в предложении FROM SQL, как если бы он был подзаголовком, запрос. Синтаксис Cypher можно использовать в предложении FROM для использования набора данных вершин или ребер, хранящихся в графе DB как данные в инструкции SQL.

Cинтаксис:

SELECT [column_name]
FROM ({table_name|SQLquery|CYPHERquery})
WHERE [column_name operator value];

Пример:

SELECT n->>'name' as name FROM history, (MATCH (n:dev) RETURN n) as dev where history.year > (n->>'year')::int;
name
---------
someone
(1 row)

SQL в Cypher

При запросе содержимого графа DB с запросами Cypher вы можете использовать предложение match и where, когда вы хотите выполнить поиск с использованием специальных данных RDB. Однако результирующий набор данных в SQL-запросах должен быть согласован- чтобы вернуть один ряд результатов. Синтаксис:

MATCH [table_name]
WHERE (column_name operator {value|SQLquery|CYPHERquery})
RETURN [column_name];

Пример:

MATCH (n:dev)
WHERE n.year < to_jsonb((SELECT year FROM history WHERE event = 'AgensGraph'))
RETURN properties(n) AS n;
n
-----------------------------------
{"name": "someone", "year": 2015}
(1 row)

[Источник 8].

Источники

  1. Creative Commons 3.0 License // Creative Commons. [2019-2019]. Дата обновления: 15.12.2018. URL: https://creativecommons.org/licenses/by-sa/3.0/ (дата обращения: 20.01.2019)
  2. Open Cypher // Opencypher.org. [2019-2019]. Дата обновления: 05.11.2018. URL: http://www.opencypher.org (дата обращения: 20.01.2019)
  3. Release Notes // AgensGraph Documentation [2019-2019]. Дата обновления: 20.12.2018. URL: https://bitnine.net/documentations/manual/agens_graph_quick_guide.html#release-notes (дата обращения: 20.01.2019)
  4. Features // AgensGraph Documentation [2019-2019]. Дата обновления: 11.11.2018. URL: https://bitnine.net/documentations/manual/agens_graph_quick_guide.html#features (дата обращения: 20.01.2019)
  5. 5,0 5,1 Data Model // AgensGraph Documentation [2019-2019]. Дата обновления: 03.12.2018. URL: https://bitnine.net/documentations/manual/agens_graph_quick_guide.html#data-model (дата обращения: 20.01.2019)
  6. Installation // AgensGraph Documentation [2019-2019]. Дата обновления: 05.02.2018. URL: https://bitnine.net/documentations/manual/agens_graph_quick_guide.html#installation (дата обращения: 20.01.2019)
  7. Data Definition Language // AgensGraph Documentation [2019-2019]. Дата обновления: 09.06.2018. URL: https://bitnine.net/documentations/manual/agens_graph_quick_guide.html#data-definition-language (дата обращения: 20.01.2019)
  8. AgensGraph Query // AgensGraph Documentation [2019-2019]. Дата обновления: 10.09.2018. URL: https://bitnine.net/documentations/manual/agens_graph_quick_guide.html#agensgraph-query (дата обращения: 20.01.2019)