Массивы и функции условий

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