Функции для массивов и условий

ALL()

ALL(cond FOR var IN json.array) применяется к JSON-массивам и возвращает 1, если условие истинно для всех элементов массива, и 0 в противном случае. cond — это общее выражение, которое также может использовать var в качестве текущего значения элемента массива внутри себя.

‹›
  • ALL() with json
  • ALL() with json ex. 2
📋
select *, ALL(x>0 AND x<4 FOR x IN j.ar) from tbl
‹›
Response
+------+--------------+--------------------------------+
| id   | j            | all(x>0 and x<4 for x in j.ar) |
+------+--------------+--------------------------------+
|    1 | {"ar":[1,3]} |                              1 |
|    2 | {"ar":[3,7]} |                              0 |
+------+--------------+--------------------------------+
2 rows in set (0.00 sec)

ALL(mva) — это специальный конструктор для многозначных атрибутов. При использовании с операторами сравнения (включая сравнение с IN()) возвращает 1, если все значения из MVA-атрибута найдены среди сравниваемых значений.

‹›
  • ALL() with MVA
  • ALL() with MVA and IN()
📋
select * from tbl where all(m) >= 1
‹›
Response
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)

Чтобы сравнить MVA-атрибут с массивом, избегайте использования <mva> NOT ALL(); вместо этого используйте ALL(<mva>) NOT IN().

‹›
  • ALL() with MVA and NOT IN()
ALL() with MVA and NOT IN()
📋
select * from tbl where all(m) not in (2, 4)
‹›
Response
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)

ALL(string list) — это специальная операция для фильтрации строковых тегов.

Если все слова, перечисленные в качестве аргументов ALL(), присутствуют в атрибуте, фильтр срабатывает. Необязательный NOT инвертирует логику.

Этот фильтр внутренне использует покдокументное сопоставление, поэтому в случае запроса с полным сканированием он может работать медленнее, чем ожидается. Он предназначен для атрибутов, которые не индексируются, например, вычисляемых выражений или тегов в таблицах PQ. Если вам нужна такая фильтрация, рассмотрите вариант размещения строкового атрибута как полнотекстового поля с последующим использованием полнотекстового оператора match(), который вызовет полнотекстовый поиск.

‹›
  • ALL() with strings
  • ALL() with strings and NOT
📋
select * from tbl where tags all('bug', 'release')
‹›
Response
+------+---------------------------+
| id   | tags                      |
+------+---------------------------+
|    1 | bug priority_high release |
|    2 | bug priority_low release  |
+------+---------------------------+
2 rows in set (0.00 sec)

ANY()

ANY(cond FOR var IN json.array) применяется к JSON-массивам и возвращает 1, если условие истинно для любого элемента массива, и 0 в противном случае. cond — это общее выражение, которое также может использовать var в качестве текущего значения элемента массива внутри себя.

‹›
  • ANY() with json
  • ANY() with json ex. 2
📋
select *, ANY(x>5 AND x<10 FOR x IN j.ar) from tbl
‹›
Response
+------+--------------+---------------------------------+
| id   | j            | any(x>5 and x<10 for x in j.ar) |
+------+--------------+---------------------------------+
|    1 | {"ar":[1,3]} |                               0 |
|    2 | {"ar":[3,7]} |                               1 |
+------+--------------+---------------------------------+
2 rows in set (0.00 sec)

ANY(mva) — это специальный конструктор для многозначных атрибутов. При использовании с операторами сравнения (включая сравнение с IN()) возвращает 1, если любое из значений MVA найдено среди сравниваемых значений.

При сравнении массива с помощью IN(), по умолчанию подразумевается ANY(), если не указано иное, но будет выдано предупреждение об отсутствующем конструкторе.

‹›
  • ANY() with MVA
  • ANY() with MVA and IN()
📋
mysql> select * from tbl
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.01 sec)
mysql> select * from tbl where any(m) > 5
+------+------+
| id   | m    |
+------+------+
|    2 | 3,7  |
+------+------+
1 row in set (0.00 sec)
‹›
Response
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)

Чтобы сравнить MVA-атрибут с массивом, избегайте использования <mva> NOT ANY(); вместо этого используйте <mva> NOT IN() или ANY(<mva>) NOT IN().

‹›
  • ANY() with MVA and NOT IN()
ANY() with MVA and NOT IN()
📋
mysql> select * from tbl
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)
mysql> select * from tbl where any(m) not in (1, 3, 5)
+------+------+
| id   | m    |
+------+------+
|    2 | 3,7  |
+------+------+
1 row in set (0.00 sec)

ANY(string list) — это специальная операция для фильтрации строковых тегов.

Если любое из слов, перечисленных в качестве аргументов ANY(), присутствует в атрибуте, фильтр срабатывает. Необязательный NOT инвертирует логику.

Этот фильтр внутренне использует покдокументное сопоставление, поэтому в случае запроса с полным сканированием он может работать медленнее, чем ожидается. Он предназначен для атрибутов, которые не индексируются, например, вычисляемых выражений или тегов в таблицах PQ. Если вам нужна такая фильтрация, рассмотрите вариант размещения строкового атрибута как полнотекстового поля с последующим использованием полнотекстового оператора match(), который вызовет полнотекстовый поиск.

‹›
  • ANY() with strings
  • ANY() with strings and NOT
📋
select * from tbl where tags any('bug', 'feature')
‹›
Response
+------+---------------------------+
| id   | tags                      |
+------+---------------------------+
|    1 | bug priority_high release |
|    2 | bug priority_low release  |
+------+---------------------------+
2 rows in set (0.00 sec)

CONTAINS()

CONTAINS(polygon, x, y) проверяет, находится ли точка (x,y) внутри заданного полигона, и возвращает 1, если истинно, или 0, если ложно. Полигон должен быть задан с помощью функции POLY2D(). Первая функция предназначена для "маленьких" полигонов, то есть со стороной менее 500 км (300 миль), и она не учитывает кривизну Земли для скорости. Для больших расстояний следует использовать GEOPOLY2D, которая разбивает заданный полигон на меньшие части, учитывая кривизну Земли.

IF()

Поведение IF() немного отличается от его аналога в MySQL. Она принимает 3 аргумента, проверяет, равен ли первый аргумент 0.0, возвращает второй аргумент, если он не равен нулю, или третий, когда равен. Обратите внимание, что в отличие от операторов сравнения, IF() не использует порог! Поэтому безопасно использовать результаты сравнений в качестве её первого аргумента, но арифметические операторы могут давать неожиданные результаты. Например, следующие два вызова дадут разные результаты, хотя они логически эквивалентны:

‹›
  • IF()
IF()
📋
IF ( sqrt(3)*sqrt(3)-3<>0, a, b )
IF ( sqrt(3)*sqrt(3)-3, a, b )

В первом случае оператор сравнения <> вернёт 0.0 (ложь) из-за порога, и IF() всегда вернёт ** в результате. Во втором случае то же выражение sqrt(3)*sqrt(3)-3 будет сравниваться с нулём без порога самой функцией IF(). Однако его значение будет немного отличаться от нуля из-за ограниченной точности вычислений с плавающей запятой. Из-за этого сравнение с 0.0, выполняемое IF(), не пройдёт, и второй вариант вернёт 'a' в качестве результата.

HISTOGRAM()

HISTOGRAM(expr, {hist_interval=size, hist_offset=value}) принимает размер интервала и возвращает номер интервала для значения. Ключевая функция:

key_of_the_bucket = interval + offset * floor ( ( value - offset ) / interval )

Аргумент гистограммы interval должен быть положительным. Аргумент гистограммы offset должен быть положительным и меньше interval. Используется в агрегации, FACET и группировке.

‹›
  • HISTOGRAM()
HISTOGRAM()
📋
SELECT COUNT(*),
HISTOGRAM(price, {hist_interval=100}) as price_range
FROM facets
GROUP BY price_range ORDER BY price_range ASC;

IN()

IN(expr,val1,val2,...) принимает 2 или более аргументов и возвращает 1, если первый аргумент (expr) равен любому из остальных аргументов (val1..valN), или 0 в противном случае. В настоящее время все проверяемые значения (но не само выражение) должны быть константами. Константы предварительно сортируются, и используется бинарный поиск, поэтому IN() даже для большого произвольного списка констант будет очень быстрым. Первый аргумент также может быть атрибутом MVA. В этом случае IN() вернет 1, если любое из значений MVA равно любому из других аргументов. IN() также поддерживает синтаксис IN(expr,@uservar) для проверки, принадлежит ли значение списку в заданной глобальной пользовательской переменной. Первый аргумент может быть атрибутом JSON.

INDEXOF()

INDEXOF(cond FOR var IN json.array) функция перебирает все элементы в массиве и возвращает индекс первого элемента, для которого 'cond' истинно, и -1, если 'cond' ложно для каждого элемента в массиве.

INTERVAL()

INTERVAL(expr,point1,point2,point3,...) принимает 2 или более аргументов и возвращает индекс аргумента, который меньше первого аргумента: возвращает 0, если expr<point1, 1, если point1<=expr<point2, и так далее. Для корректной работы этой функции требуется, чтобы point1<point2<...<pointN.

LENGTH()

LENGTH(attr_mva) функция возвращает количество элементов в наборе MVA. Работает как с 32-битными, так и с 64-битными атрибутами MVA. LENGTH(attr_json) возвращает длину поля в JSON. Возвращаемое значение зависит от типа поля. Например, LENGTH(json_attr.some_int) всегда возвращает 1, а LENGTH(json_attr.some_array) возвращает количество элементов в массиве. LENGTH(string_expr) функция возвращает длину строки, полученной из выражения. TO_STRING() должно заключать выражение, независимо от того, возвращает ли выражение не-строку или это просто строковый атрибут.

RANGE()

RANGE(expr, {range_from=value,range_to=value}) принимает набор диапазонов и возвращает номер интервала для значения. Это выражение включает значение range_from и исключает значение range_to для каждого диапазона. Диапазон может быть открытым — иметь только значение range_from или только значение range_to. Используется в агрегации, FACET и группировке.

‹›
  • RANGE()
RANGE()
📋
SELECT COUNT(*),
RANGE(price, {range_to=150},{range_from=150,range_to=300},{range_from=300}) price_range
FROM facets
GROUP BY price_range ORDER BY price_range ASC;

REMAP()

REMAP(condition, expression, (cond1, cond2, ...), (expr1, expr2, ...)) функция позволяет делать исключения для значений выражения в зависимости от значений условия. Выражение условия всегда должно давать целое число, в то время как выражение может давать целое число или число с плавающей точкой.

‹›
  • REMAP()
  • Another example
📋
SELECT id, size, REMAP(size, 15, (5,6,7,8), (1,1,2,2)) s
FROM products
ORDER BY s ASC;

Это поместит документы с размерами 5 и 6 первыми, за ними последуют размеры 7 и 8. В случае, если есть исходное значение, не указанное в массиве (например, размер 10), оно по умолчанию будет равно 15 и, в данном случае, будет помещено в конец.

Last modified: August 28, 2025