AGE использует пользовательский тип данных agtype, который является единственным типом, возвращаемым функциями AGE. Тип agtype представляет собой надмножество JSON и является собственной реализацией типа jsonb из PostgreSQL.
В Cypher значение null обозначает отсутствующее или неопределённое значение. По смыслу null означает «отсутствующее неизвестное значение» и ведёт себя иначе, чем все остальные значения. Например, обращение к несуществующему свойству вершины возвращает null. Большинство выражений, получающих null на вход, также возвращают null, включая логические предикаты в предложении WHERE. В таких случаях любое значение, не равное true, рассматривается как false. null не равен null: отсутствие информации о равенстве двух значений не означает, что они равны. Поэтому выражение null = null вычисляется в null, а не в true.
Запрос
SELECT *
FROM cypher('graph_name', $$
RETURN NULL
$$) AS (null_result agtype);
null отображается как пустое поле.
Результат
null_result
(1 строка)
Понятие NULL в agtype и в PostgreSQL идентично понятию null в Cypher.
Тип integer хранит целые числа — числовые значения без дробной части. Это 64-битное знаковое целое, поддерживающее диапазон от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. Попытка сохранить значение за пределами этого диапазона вызовет ошибку.
Тип integer обеспечивает оптимальный баланс между диапазоном значений, размером хранилища и производительностью. Тип smallint используется только при жёстком ограничении дискового пространства. Тип bigint предназначен для случаев, когда диапазон integer недостаточен.
Запрос
SELECT *
FROM cypher('graph_name', $$
RETURN 1
$$) AS (int_result agtype);
Результат
| int_result |
| ---------- |
| 1 |
(1 строка)
Тип float — это приблизительный числовой тип переменной точности, соответствующий стандарту IEEE-754.
«Приблизительность» означает, что некоторые значения невозможно точно представить во внутреннем формате и они хранятся как приближения. Поэтому при чтении и записи могут возникать небольшие расхождения. Управление такими погрешностями — и их распространением в арифметических операциях — составляет отдельную область математики и информатики. Хотя её детальное рассмотрение выходит за рамки данного документа, следует учитывать следующие ключевые моменты:
numeric. Значения, слишком большие или слишком малые, вызывают ошибку. Слишком точные входные данные могут быть округлены. Значения, слишком близкие к нулю для различимого представления, приводят к ошибке переполнения вниз (underflow).
Помимо обычных числовых значений, float поддерживает несколько специальных значений:
Infinity -Infinity NaNЭти значения соответствуют специальным значениям IEEE 754: «положительная бесконечность», «отрицательная бесконечность» и «не число». Чтобы использовать их как литералы в командах Cypher, их необходимо заключить в кавычки и явно привести, например:
SET x.float_value = '-Infinity'::float
Строки-литералы для этих значений сравниваются без учёта регистра.
Для указания значения float необходимо включить десятичную точку.
Запрос
SELECT *
FROM cypher('graph_name', $$
RETURN 1.0
$$) AS (float_result agtype);
Результат
| float_result |
| ------------ |
| 1.0 |
(1 строка)
— Появится скоро —
AGE предоставляет стандартный логический тип Cypher. Тип boolean имеет три возможных состояния: true, false и третье состояние — unknown, которое представляется значением agtype null.
Логические литералы записываются в запросах Cypher с помощью ключевых слов TRUE, FALSE и NULL.
Запрос
SELECT *
FROM cypher('graph_name', $$
RETURN TRUE
$$) AS (boolean_result agtype);
В отличие от PostgreSQL, AGE выводит полные слова (true, false), а не односимвольные сокращения (t, f).
Результат
| boolean_result |
| -------------- |
| true |
(1 строка)
Литералы строк agtype поддерживают следующие последовательности экранирования:
| Последовательность экранирования | Символ |
|---|---|
\t |
Табуляция |
\b |
Возврат на шаг |
\n |
Перевод строки |
\r |
Возврат каретки |
\f |
Разрыв страницы |
' |
Одинарная кавычка |
" |
Двойная кавычка |
\\ |
Обратная косая черта |
\uXXXX |
Кодовая позиция Unicode UTF-16 (ровно четыре шестнадцатеричные цифры после \u) |
Строки заключаются в одинарные кавычки ('). На выходе используются двойные кавычки (").
Запрос
SELECT *
FROM cypher('graph_name', $$
RETURN 'This is a string'
$$) AS (string_result agtype);
Результат
| string_result |
| ------------------ |
| "This is a string" |
(1 строка)
Все примеры используют предложения WITH и RETURN.
Списки создаются с помощью квадратных скобок с элементами, разделёнными запятыми.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst
$$) AS (lst agtype);
Результат
| lst |
| ---------------------------------- |
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |
(1 строка)
Списки могут содержать значения null. В отличие от самостоятельного null, значение null внутри списка отображается как буквальный текст null.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [null] AS lst
RETURN lst
$$) AS (lst agtype);
Результат
| lst |
| ------- |
| [null] |
(1 строка)
Для доступа к отдельным элементам списка используются квадратные скобки. Синтаксис list[start..end] возвращает элементы с индекса start (включительно) по индекс end (исключительно).
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[3]
$$) AS (element agtype);
Результат
| element |
| ------- |
| 3 |
(1 строка)
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, {key: 'key_value'}, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst
$$) AS (map_value agtype);
Результат
| map_value |
| ----------------------------------------------------- |
| [0, {"key": "key_value"}, 2, 3, 4, 5, 6, 7, 8, 9, 10] |
(1 строка)
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, {key: 'key_value'}, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[1].key
$$) AS (map_value agtype);
Результат
| map_value |
| ----------- |
| "key_value" |
(1 строка)
Отрицательные индексы отсчитываются от конца списка.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[-3]
$$) AS (element agtype);
Результат
| element |
| ------- |
| 8 |
(1 строка)
Квадратные скобки поддерживают диапазоны для извлечения подпоследовательностей.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[0..3]
$$) AS (element agtype);
Результат
| element |
| --------- |
| [0, 1, 2] |
(1 строка)
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[0..-5]
$$) AS (lst agtype);
Результат
| lst |
| ------------------ |
| [0, 1, 2, 3, 4, 5] |
(1 строка)
Пропуск начального индекса подразумевает значение 0.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[..4]
$$) AS (lst agtype);
Результат
| lst |
| ------------ |
| [0, 1, 2, 3] |
(1 строка)
Пропуск конечного индекса подразумевает длину списка.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[-5..]
$$) AS (lst agtype);
Результат
| lst |
| ------------------ |
| [6, 7, 8, 9, 10] |
(1 строка)
Срезы с выходом за границы усекаются без предупреждения. При обращении к отдельному элементу за пределами границ возвращается null.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[15]
$$) AS (element agtype);
Результат
| element |
| ------- |
| |
(1 строка)
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] AS lst
RETURN lst[5..15]
$$) AS (element agtype);
Результат
| element |
| ------------------- |
| [5, 6, 7, 8, 9, 10] |
(1 строка)
Карты можно создавать непосредственно в Cypher.
Простую карту можно построить из базовых значений agtype.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH {int_key: 1, float_key: 1.0, numeric_key: 1::numeric, bool_key: true, string_key: 'Value'} AS m
RETURN m
$$) AS (m agtype);
Результат
| m |
| ---------------------------------------------------------------------------------------------------- |
| {"int_key": 1, "bool_key": true, "float_key": 1.0, "string_key": "Value", "numeric_key": 1::numeric} |
(1 строка)
Карты могут содержать составные типы — например, списки и вложенные карты.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH {listKey: [{inner: 'Map1'}, {inner: 'Map2'}], mapKey: {i: 0}} AS m
RETURN m
$$) AS (m agtype);
Результат
| m |
| ----------------------------------------------------------------------- |
| {"mapKey": {"i": 0}, "listKey": [{"inner": "Map1"}, {"inner": "Map2"}]} |
(1 строка)
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH {int_key: 1, float_key: 1.0, numeric_key: 1::numeric, bool_key: true, string_key: 'Value'} AS m
RETURN m.int_key
$$) AS (int_key agtype);
Результат
| int_key |
| ------- |
| 1 |
(1 строка)
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH {listKey: [{inner: 'Map1'}, {inner: 'Map2'}], mapKey: {i: 0}} AS m
RETURN m.listKey[0]
$$) AS (m agtype);
Результат
| m |
| ----------------- |
| {"inner": "Map1"} |
(1 строка)
Сущности имеют уникальные и сравнимые идентификаторы, используемые для определения равенства.
Каждой сущности назначается набор свойств, каждый из которых в этом наборе уникально идентифицируется по имени свойства.
Простым сущностям назначается уникальный graphid. graphid — это уникальная комбинация идентификатора метки и порядкового номера, назначенного для каждой метки. Обратите внимание: graphid могут совпадать в разных графах.
graphid по своей сути представляет собой знаковое 64-битное целое число (int64).
64 бита разбиты следующим образом:
<--- 16 бит ---> |
<----------- 48 бит -----------> |
|---|---|
| Идентификатор метки | Номер записи |
| (биты 63–48) | (биты 47–0) |
1 до 65535 (PG_UINT16_MAX). Значение 0 недопустимо. 1 до 281474976710655 (0x0000ffffffffffff). Значение 0 недопустимо.Метки — это идентификаторы, классифицирующие вершины и рёбра по категориям.
Сведения о создании сущностей с метками см. в разделе о предложении CREATE.
Примечание!
В YMatrix AGE метки реализованы как таблицы базы данных — то есть одна метка соответствует ровно одной таблице.
Как вершины, так и рёбра могут иметь свойства. Свойства — это пары «ключ–значение», где имя каждого свойства должно быть строкой.
vertex — это фундаментальная сущность графа, обладающая самостоятельным существованием и уникальной идентичностью. Формат данных
| Имя поля | Описание |
|---|---|
id |
graphid вершины |
label |
Имя метки вершины |
properties |
Свойства, связанные с вершиной |
{id:1; label: 'label_name'; properties: {prop1: value1, prop2: value2}}::vertex
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH {id: 0, label: "label_name", properties: {i: 0}}::vertex AS v
RETURN v
$$) AS (v agtype);
Результат
| v |
| ---------------------------------------------------------------- |
| {"id": 0, "label": "label_name", "properties": {"i": 0}}::vertex |
(1 строка)
edge — это направленное соединение между двумя узлами: исходным и целевым. Исходящее ребро рассматривается с точки зрения исходного узла; входящее ребро — с точки зрения целевого узла. Каждому ребру назначается ровно один тип ребра.
Формат данных
| Имя поля | Описание |
|---|---|
id |
graphid ребра |
startid |
graphid исходного узла |
endid |
graphid целевого узла |
label |
Имя метки ребра |
properties |
Свойства, связанные с ребром |
Формат вывода
{id: 3; startid: 1; endid: 2; label: 'edge_label'; properties: {prop1: value1, prop2: value2}}::edge
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH {id: 2, start_id: 0, end_id: 1, label: "label_name", properties: {i: 0}}::edge AS e
RETURN e
$$) AS (e agtype);
Результат
| e |
| ------------------------------------------------------------------------------------------ |
| {"id": 2, "label": "label_name", "end_id": 1, "start_id": 0, "properties": {"i": 0}}::edge |
(1 строка)
path — это чередующаяся последовательность вершин и рёбер. Путь должен начинаться с вершины и содержать хотя бы одно ребро.
Запрос
SELECT *
FROM cypher('graph_name', $$
WITH [{id: 0, label: "label_name_1", properties: {i: 0}}::vertex,
{id: 2, start_id: 0, end_id: 1, label: "edge_label", properties: {i: 0}}::edge,
{id: 1, label: "label_name_2", properties: {}}::vertex
]::path AS p
RETURN p
$$) AS (p agtype);
Результат
| p |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [{"id": 0, "label": "label_name_1", "properties": {"i": 0}}::vertex, {"id": 2, "label": "edge_label", "end_id": 1, "start_id": 0, "properties": {"i": 0}}::edge, {"id": 1, "label": "label_name_2", "properties": {}}::vertex]::path |
(1 строка)