Строковые выражения#

Введение#

В DataSpace можно использовать строковые выражения, которые позволяют моделировать выражения различных уровней сложности.

Поддерживаются следующие типы строковых выражений:

  • примитивное выражение;

  • коллекция примитивных выражений;

  • сущность;

  • коллекция сущностей;

  • условие.

Базовые объекты#

В грамматике строковых выражений предусмотрены следующие базовые объекты:

Корневая сущность#

Корневая сущность имеет тип сущность, обозначается с помощью ключевого слова root и имеет настройку спецификацииtype (тип сущности) — позволяет уточнить тип сущности для обращения к свойствам типа-потомка.

Корневую сущность можно, например, использовать для обращения к искомой сущности при поиске.

Пример 1

Условие: код продукта соответствует шаблону product% (при поиске продуктов).

root.code $like 'product%'

Пример 2

Примитивное значение: ставка депозита больше 10 (при поиске продуктов).

root{type = Deposit}.rate > 10

Примечание

Рекомендуется для обращения к корневой сущности использовать текущий элемент в ситуациях, когда в контексте они обозначают один и тот же объект.

Элемент коллекции#

Элемент коллекции имеет тип сущность или примитивное выражение в зависимости от контекста. Обозначается с помощью ключевого слова elem. В случае, если элемент имеет тип сущность, то у него присутствует настройка спецификации type (тип сущности) — позволяет уточнить тип сущности-элемента для обращения к свойствам типа-потомка.

Элемент коллекции можно использовать в поисках для обращения к элементу коллекции при фильтрации коллекции.

Пример 1

Условие: код сервиса начинается с кода продукта (при запросе сервисов при поиске продуктов).

elem.code $like root.code + '%'

Пример 2

Условие: состояние начинается с символа 'a' (при запросе состояний при поиске продуктов).

elem $like 'a%'

Примечание

Рекомендуется для обращения к элементу коллекции использовать текущий элемент.

Текущий элемент#

Текущий элемент имеет тип сущность или примитивное значение в зависимости от контекста. Обозначается с помощью ключевого слова it. Если элемент имеет тип сущность, то у него присутствует настройка спецификации type (тип сущности) — позволяет уточнить тип сущности-элемента для обращения к свойствам типа-потомка.

Текущий элемент используется для обращения к текущему рассматриваемому элементу выражения. Например, в случае условия поиска текущий элемент является эквивалентом корневой сущности, а в случае фильтрации коллекции — элемента коллекции.

Пример 1

Условие: код продукта соответствует шаблону 'product%' (при поиске продуктов).

it.code $like 'product%'

Пример 2

Условие: код сервиса начинается с кода продукта (при запросе сервисов при поиске продуктов).

it.code $like root.code + '%'

Сущность под псевдонимом#

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

При обращении к сущности под псевдонимом можно использовать настройку спецификации type — тип сущности. Параметр позволяет уточнить тип сущности для обращения к свойствам типа-потомка.

Пример

Условие: код продукта под псевдонимом 'product' равен 'product1' (при запросе сервисов у запрошенных продуктов при поиске документов).

@product.code == 'product1'

Сущности#

Сущности имеют тип коллекция сущностей, обозначаются с помощью ключевого слова entities и имеют следующие настройки спецификации:

  • type — тип сущностей (обязательная настройка);

  • elemAlias — псевдоним элемента;

  • cond — условие фильтрации сущностей.

Пример

Условие: существуют контракты, код которых равен коду продукта (при поиске продуктов).

entities{type = Contract, cond = it.code == root.code}.$exists

Примитивное значение#

Имеется возможность задать базовые примитивные выражения:

Тип

Формат

Пример значения

Строка

Строка, обрамленная одинарными кавычками ('). Для обозначения одинарной кавычки необходимо написать одинарную кавычку два раза подряд ('')

'I''m a string'

Целое число

123

Вещественное число

Целая и вещественная часть отделены точкой. Использование экспоненциальной записи не допускается

123.456

Дата

ISO 8601 с префиксом D

D2021-04-12

Дата и время

ISO 8601 с префиксом D

D2021-04-12T13:18:10.123

Дата и время со смещением

ISO 8601 с префиксом D

D2021-04-12T13:18:10.123+03:00

Время

ISO 8601 с префиксом T

T13:18:10.123

Логическое значение

true или false

Текущая метка времени#

Лексема now представляет текущее время БД (с учетом часового пояса).

Пример

Коллекция сущностей: заблокированные прикладной блокировкой продукты.

entities{type = Product, cond = it.syalUnlockTime >= now}

Спецификация#

Некоторые объекты могут иметь дополнительные настройки (например, type для корневой сущности). Для задания данных настроек вводится понятие спецификации.

Спецификацию для объекта можно указать в фигурных скобках ({ и }), а настройки указываются следующим образом и перечисляются через запятую:

${наименование настройки} = ${значение настройки}`

Пример

Коллекция сущностей: продукты, код которых соответствует шаблону 'product%'.

entities{type = Product, cond = it.code $like 'product%'}

Методы выражений#

Каждый тип выражения предоставляет набор методов, которые можно использовать при описании выражения.

Методы примитивных выражений#

Для примитивных выражений доступны следующие методы:

  • отрицание: -${примитивное выражение} (например, -it.number);

  • приведение в верхний регистр: ${примитивное выражение}.$upper (например, it.string.$upper);

  • приведение в нижний регистр: ${примитивное выражение}.$lower (например, it.string.$lower);

  • длина: ${примитивное выражение}.$length (например, it.string.$length);

  • отсечение пробельных символов в начале и конце: ${примитивное выражение}.$trim (например, it.string.$trim);

  • отсечение пробельных символов в начале: ${примитивное выражение}.$ltrim (например, it.string.$ltrim);

  • отсечение пробельных символов в конце: ${примитивное выражение}.$rtrim (например, it.string.$rtrim);

  • округление: ${примитивное выражение}.$round (например, it.number.$round);

  • округление вверх: ${примитивное выражение}.$ceil (например, it.number.$ceil);

  • округление вниз: ${примитивное выражение}.$floor (например, it.number.$floor);

  • хеш: ${примитивное выражение}.$hash (например, it.string.$hash);

  • приведение к строке: ${примитивное выражение}.$asString (например, it.number.$asString);

  • приведение к большому десятичному числу: ${примитивное выражение}.$asBigDecimal (например, it.string.$asBigDecimal);

  • приведение к дате: ${примитивное выражение}.$asDate (например, it.string.$asDate);

  • приведение к дате и времени: ${примитивное выражение}.$asDateTime (например, it.string.$asDateTime);

  • приведение к дате и времени со смещением: ${примитивное выражение}.$asOffsetDateTime (например, it.string.$asOffsetDateTime);

  • приведение ко времени: ${примитивное выражение}.$asTime (например, it.string.$asTime);

  • год: ${примитивное выражение}.$year (например, it.offsetDateTime.$year);

  • месяц: ${примитивное выражение}.$month (например, it.offsetDateTime.$month);

  • день: ${примитивное выражение}.$day (например, it.offsetDateTime.$day);

  • час: ${примитивное выражение}.$hour (например, it.offsetDateTime.$hour);

  • минута: ${примитивное выражение}.$minute (например, it.offsetDateTime.$minute);

  • секунда: ${примитивное выражение}.$second (например, it.offsetDateTime.$second);

  • час смещения: ${примитивное выражение}.$offsetHour (например, it.offsetDateTime.$offsetHour);

  • минута смещения: ${примитивное выражение}.$offsetMinute (например, it.offsetDateTime.$offsetMinute);

  • дата: ${примитивное выражение}.$date (например, it.offsetDateTime.$date);

  • время: ${примитивное выражение}.$time (например, it.offsetDateTime.$time);

  • смещение: ${примитивное выражение}.$offset (например, it.offsetDateTime.$offset);

  • модуль числа: ${примитивное выражение}.$abs (например, it.number.$abs);

  • побитовое отрицание: ~${примитивное выражение} (например, ~it.number);

  • побитовое "И": ${примитивное выражение} & ${примитивное выражение} (например, it.number & 4);

  • побитовое "Или": ${примитивное выражение} | ${примитивное выражение} (например, it.number | 4);

  • побитовое "Исключающее или": ${примитивное выражение} ^ ${примитивное выражение} (например, it.number ^ 4);

  • сдвиг влево: ${примитивное выражение} << ${примитивное выражение} (например, it.number << 4);

  • сдвиг вправо: ${примитивное выражение} >> ${примитивное выражение} (например, it.number >> 4);

  • сложение: ${примитивное выражение} + ${примитивное выражение} (например, it.number + 4);

  • разность: ${примитивное выражение} ${примитивное выражение} (например, it.number 4);

  • произведение: ${примитивное выражение} * ${примитивное выражение} (например, it.number * 4);

  • деление: ${примитивное выражение} / ${примитивное выражение} (например, it.number / 4);

  • остаток от деления: ${примитивное выражение} % ${примитивное выражение}, ${примитивное выражение} $mod ${примитивное выражение} (например, it.number % 4, it.number $mod 4);

  • подстрока: ${примитивное выражение}.$substr(${примитивное выражение (индекс начала)}) (например, it.string.$substr(4));

  • подстрока: ${примитивное выражение}.$substr(${примитивное выражение (индекс начала)}, ${примитивное выражение (длина)}) (например, it.string.$substr(4, it.number));

  • замена: ${примитивное выражение}.$replace(${примитивное выражение (заменяемая строка)}, ${примитивное выражение (новая строка)}) (например, it.string.$replace('code', it.name));

  • строка с заполнением слева: ${примитивное выражение}.$lpad(${примитивное выражение}, ${примитивное выражение}) (например, it.string.$lpad(10, ' '));

  • строка с заполнением справа: ${примитивное выражение}.$rpad(${примитивное выражение}, ${примитивное выражение}) (например, it.string.$rpad(10, ' '));

  • добавление миллисекунд: ${примитивное выражение}.$addMilliseconds(${примитивное выражение}) (например, it.date.$addMilliseconds(1));

  • добавление секунд: ${примитивное выражение}.$addSeconds(${примитивное выражение}) (например, it.date.$addSeconds(1));

  • добавление минут: ${примитивное выражение}.$addMinutes(${примитивное выражение}) (например, it.date.$addMinutes(1));

  • добавление часов: ${примитивное выражение}.$addHours(${примитивное выражение}) (например, it.date.$addHours(1));

  • добавление дней: ${примитивное выражение}.$addDays(${примитивное выражение}) (например, it.date.$addDays(1));

  • добавление месяцев: ${примитивное выражение}.$addMonths(${примитивное выражение}) (например, it.date.$addMonths(1));

  • добавление годов: ${примитивное выражение}.$addYears(${примитивное выражение}) (например, it.date.$addYears(1));

  • вычитание миллисекунд: ${примитивное выражение}.$subMilliseconds(${примитивное выражение}) (например, it.date.$subMilliseconds(1));

  • вычитание секунд: ${примитивное выражение}.$subSeconds(${примитивное выражение}) (например, it.date.$subSeconds(1));

  • вычитание минут: ${примитивное выражение}.$subMinutes(${примитивное выражение}) (например, it.date.$subMinutes(1));

  • вычитание часов: ${примитивное выражение}.$subHours(${примитивное выражение}) (например, it.date.$subHours(1));

  • вычитание дней: ${примитивное выражение}.$subDays(${примитивное выражение}) (например, it.date.$subDays(1));

  • вычитание месяцев: ${примитивное выражение}.$subMonths(${примитивное выражение}) (например, it.date.$subMonths(1));

  • вычитание годов: ${примитивное выражение}.$subYears(${примитивное выражение}) (например, it.date.$subYears(1));

  • условие "Равен null": ${примитивное выражение} == null (например, it.code == null);

  • условие "Не равен null": ${примитивное выражение} != null (например, it.code != null);

  • условие "Равен": ${примитивное выражение} == ${примитивное выражение} (например, it.code == 'service');

  • условие "Не равен": ${примитивное выражение} != ${примитивное выражение} (например, it.code != 'service');

  • условие "Больше": ${примитивное выражение} > ${примитивное выражение} (например, it.number > 4);

  • условие "Меньше или равно": ${примитивное выражение} <= ${примитивное выражение} (например, it.number <= 4);

  • условие "Меньше": ${примитивное выражение} < ${примитивное выражение} (например, it.number < 4);

  • условие "Подобен": ${примитивное выражение} $like ${примитивное выражение} (например, it.code $like 'service%');

  • условие "Между": ${примитивное выражение} $between (${примитивное выражение}, ${примитивное значение}) (например, it.number $between (4, it.number2));

  • условие "В": ${примитивное выражение} $in [${примитивное выражение}, ...] (например, it.number $in [4, it.number2, 6]);

  • условие "В": ${примитивное выражение} $in ${коллекция примитивных выражений} (например, it.number $in it.numbers);

  • агрегация "минимум": ${примитивное выражение}.$min (например, it.number.$min);

  • агрегация "максимум": ${примитивное выражение}.$max (например, it.number.$max);

  • агрегация "сумма": ${примитивное выражение}.$sum (например, it.number.$sum);

  • агрегация "среднее": ${примитивное выражение}.$avg (например, it.number.$avg);

  • агрегация "количество": ${примитивное выражение}.$count (например, it.number.$count).

Методы коллекций примитивных выражений#

Для коллекций примитивных выражений доступны следующие методы:

  • коллекция примитивных выражений на основе преобразования: ${коллекция примитивных выражений}.$map(${примитивное выражение}) (например, it.numbers.$map(it $mod root.number).$min)

  • минимум: ${коллекция примитивных выражений}.$min (например, it.numbers.$min);

  • максимум: ${коллекция примитивных выражений}.$max (например, it.numbers.$max);

  • сумма: ${коллекция примитивных выражений}.$sum (например, it.numbers.$sum);

  • среднее: ${коллекция примитивных выражений}.$avg (например, it.numbers.$avg);

  • количество элементов: ${коллекция примитивных выражений}.$count (например, it.numbers.$count);

  • условие "Существует": ${коллекция примитивных выражений}.$exists (например, it.numbers.$exists).

Методы сущностей#

Для сущностей доступны следующие методы:

  • тип: ${сущность}.$type (например, it.$type);

  • id: ${сущность}.$id либо ${сущность}.id (например, it.$id, it.id);

  • примитив: ${сущность}.${наименование свойства} (например, it.code);

  • коллекция примитивов: ${сущность}.${наименование свойства}${спецификация} (например, it.states, it.states{cond = it $like 'h%'}). Доступная настройка спецификации: cond (условие) — условие фильтрации;

  • ссылка: ${сущность}.${наименование свойства}${спецификация} (например, it.product, it.product{type = Deposit}). Доступные настройки спецификации:

    • type (тип сущности) позволяет уточнить тип сущности для обращения к свойствам типа-потомка;

    • alias (псевдоним) позволяет сохранить ссылку под псевдонимом в контекст;

  • коллекция ссылок: ${сущность}.${наименование свойства}${спецификация} (например, it.services, it.services{type = SuperService, cond = it.code like root.code + 'service%'}, it.services{elemAlias = service, cond = it.parameters{cond = it.code == @service.code}.$exists}.$exists). Доступные настройки спецификации:

    • type (тип сущности) позволяет ограничить коллекцию до коллекции, ссылки которой указывают на сущность указанного типа;

    • elemAlias (псевдоним элемента) позволяет сохранить ссылку из коллекции под псевдонимом в контекст;

    • cond (условие) условие фильтрации;

  • условие "Равен null": ${сущность} == null (например, it.product == null);

  • условие "Не равен null": ${сущность} != null (например, it.product != null);

  • условие "Существует": ${сущность}.$exists (например, it.product.$exists);

  • условие "Равно": ${сущность} == ${сущность} (например, it.product == it.document.product);

  • условие "Не равно": ${сущность} != ${сущность} (например, it.product != it.document.product);

  • условие "В": ${сущность} $in [${сущность}, ...] (например, it.product $in [it.document.product, it.document.relatedProduct]);

  • условие "В": ${сущность} $in ${коллекция сущностей} (например, it.product $in it.services.product).

Методы коллекций сущностей#

Для коллекций сущностей доступны следующие методы:

  • коллекция примитивных выражений на основе типа сущности: ${коллекция сущностей}.$type (например, it.services.$type);

  • коллекция примитивных выражений на основе id сущности: ${коллекция сущностей}.$id либо ${коллекция сущностей}.id (например, it.services.$id, it.services.id);

  • коллекция примитивных выражений на основе примитива: ${коллекция сущностей}.${наименование свойства} (например, it.services.code);

  • коллекция сущностей на основе ссылки: ${коллекция сущностей}.${наименование свойства}${спецификация} (например, it.services.product, it.services.product{type = Deposit}). Доступная настройка спецификации type (тип сущности) позволяет ограничить коллекцию до коллекции, ссылки которой указывают на сущность указанного типа;

  • коллекция примитивных выражений на основе преобразования: ${коллекция сущностей}.$map(${примитивное выражение}) (например, it.services.$map(it.operations.$count).$sum)

  • количество элементов: ${коллекция сущностей}.$count (например, it.services.$count);

  • условие "Существует": ${коллекция сущностей}.$exists (например, it.services.$exists).

Методы условий#

Для условий доступны следующие методы:

  • условие "Отрицание": !${условие} (например, !it.services.$exists);

  • условие "И": ${условие} && ${условие} (например, it.services.$exists && it.product != null);

  • условие "Или": ${условие} || ${условие} (например, it.services.$exists || it.product != null).

Общие методы#

Доступен общий метод — первый ненулевой элемент: coalesce(${примитивное выражение}, ...) (например, coalesce(it.string, it.string2)).

Приоритеты методов#

Уровень

Метод

Описание

Ассоциативность

1

||

Условие "Или"

v

2

&&

Условие "И"

v

3

!

Условие "Отрицание"

4

|

Побитовое "Или"

v

5

^

Побитовое "Исключающее или"

v

6

&

Побитовое "И"

v

7

==

Условие "Равно"

v

7

!=

Условие "Не равно"

v

8

<

Условие "Меньше"

8

>=

Условие "Больше или равно"

8

<

Условие "Меньше"

8

>=

Условие "Больше или равно"

8

$like

Условие "Подобен"

8

$between

Условие "Между"

8

$in

Условие "В"

9

<<

Сдвиг влево

9

>>

Сдвиг вправо

10

+

Сложение

v

10

-

Разность

11

*

Произведение

v

11

/

Деление

11

%, $mod

Остаток от деления

12

-

Отрицание

12

~

Побитовое отрицание

13

Все остальные методы

Примеры#

Пример 1

Условие: код продукта равен 'product1' независимо от регистра (при поиске продуктов).

it.code.$lower == 'product1'

Пример 2

Условие: суммарное время выполнение всех сервисов продукта, код которых начинается с кода продукта, не превышает 10 (при поиске продуктов).

it.services{cond = it.code $like root.code + '%'}.executionTime.$sum <= 10