Операторы массива¶
Расширение массива¶
Чтобы легко получить доступ к именованному атрибуту из всех элементов массива, AQL предлагает оператор быстрого доступа [*] для раскрытия переменных массива.
Использование оператора [*] с переменной массива будет перебирать все элементы в массиве, что позволит получить доступ к определенному атрибуту каждого элемента. Требуется, чтобы раскрываемая переменная была массивом. Результатом оператора [*] снова является массив.
Чтобы продемонстрировать оператор расширения массива, давайте продолжим со следующими тремя примерами пользовательских документов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
С оператором [*] становится легко запросить только имена друзей для каждого пользователя:
1 2 | |
Результат:
1 2 3 4 5 6 7 8 | |
Это сокращение для более длинного, семантически эквивалентного запроса:
1 2 | |
Сжатие массива¶
Чтобы свернуть (или сгладить) результаты во вложенных массивах, AQL предоставляет оператор [**]. Он работает аналогично оператору [*], но дополнительно сворачивает вложенные массивы.
Количество свернутых уровней определяется количеством используемых символов звездочки. [**] сворачивает один уровень вложенности - точно так же, как это сделали бы FLATTEN(массив) или FLATTEN(массив, 1) -, [***] сворачивает два уровня - эквивалентно FLATTEN(массив, 2) - и так далее.
Сравним оператор расширения массива с оператором сжатия массива. Например, следующий запрос создает массив имен друзей для каждого пользователя:
1 2 | |
Поскольку у нас несколько пользователей, общий результат представляет собой вложенный массив:
1 2 3 4 5 | |
Если цель состоит в том, чтобы избавиться от вложенного массива, мы можем применить оператор [**] к результату. Но просто добавление [**] к запросу не поможет, потому что u.friends — это не вложенный (многомерный) массив, а простой (одномерный) массив. Тем не менее, [**] можно использовать, если у него есть доступ к многомерному вложенному результату.
Мы можем расширить приведенный выше запрос следующим образом и по-прежнему создавать тот же вложенный результат:
1 2 3 | |
К настоящему времени добавление оператора [**] в конце запроса...
1 2 3 | |
... результат запроса становится:
1 2 3 4 5 6 7 8 9 10 11 | |
Обратите внимание, что элементы не дублируются. Для плоского массива, состоящего только из уникальных элементов, рекомендуется комбинация UNIQUE() и FLATTEN().
Встроенные выражения¶
Можно фильтровать элементы при переборе массива, ограничивать количество возвращаемых элементов и создавать проекцию, используя текущий элемент массива. Сортировка не поддерживается этой сокращенной формой.
Эти встроенные выражения могут следовать за операторами расширения и сжатия массива [* ...], [** ...] и т. д. Ключевые слова FILTER, LIMIT и RETURN должны встречаться в этом порядке, если они используются в комбинации, и могут встречаться только один раз:
anyArray[* FILTER conditions LIMIT skip,limit RETURN projection]
Пример с вложенными числами и сжатием массива:
1 2 | |
Все четные числа возвращаются в плоском массиве:
1 | |
Сложный пример с несколькими условиями, лимитом и проекцией:
1 2 3 4 5 6 7 8 | |
Для каждого пользователя возвращается не более двух вычисленных строк, основанных на друзьях с буквой a в имени и старше 40 лет:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Встроенный фильтр¶
Чтобы вернуть только имена друзей, у которых значение возраста выше, чем у самого пользователя, можно использовать встроенный FILTER:
1 2 | |
Псевдопеременная CURRENT может использоваться для доступа к текущему элементу массива. Условие FILTER может ссылаться на CURRENT или любые переменные, допустимые во внешней области видимости.
Встроенный лимит¶
Количество возвращаемых элементов может быть ограничено с помощью LIMIT. Работает так же, как операция ограничения. LIMIT должен идти после FILTER и перед RETURN, если они присутствуют.
1 2 | |
Пример выше возвращает по одному другу:
1 2 3 4 5 | |
Ряд элементов также можно пропустить и вернуть до n:
1 2 | |
Пример запроса пропускает первого друга и возвращает не более двух друзей на пользователя:
1 2 3 4 5 | |
Встроенная проекция¶
Чтобы вернуть проекцию текущего элемента, используйте RETURN. Если также присутствует FILTER, RETURN должен появиться позже.
1 2 | |
Вышеупомянутое вернется:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Оператор вопросительного знака¶
Вы можете использовать [? ... ] для массивов, чтобы проверить, соответствуют ли элементы определенным критериям, и вы можете указать, как часто они должны удовлетворяться. Оператор подобен встроенному фильтру, но с дополнительной проверкой длины и оценивается как true или false.
В следующем примере показано, как проверить, являются ли два числа в массиве четными:
1 2 | |
Число 2 после ? является квантором. Это необязательно и по умолчанию ANY. Поддерживаются следующие квантификаторы:
- Целые числа для точных количеств (например,
2) - Диапазоны чисел для количества между двумя значениями (например,
2..3) NONE(эквивалент0)ANYALLAT LEAST
За квантификатором должна следовать операция FILTER, если вы хотите указать условия. Вы можете обратиться к текущему элементу массива через псевдопеременную CURRENT в выражении фильтра. Если опустить квантификатор и операцию FILTER (только arr[?]), то arr проверяется, является ли он массивом и содержит ли он хотя бы один элемент.
Оператор вопросительного знака — это сокращение для встроенного фильтра с проверкой длины окружающего пространства. В следующей таблице сравниваются оба варианта:
| Оператор вопросительного знака | Встроенный фильтр с проверкой длины |
|---|---|
arr[? <number> FILTER <conditions>] | LENGTH(arr[* FILTER <conditions>]) == <number> |
arr[? <min>..<max> FILTER <conditions>] | IN_RANGE(LENGTH(arr[* FILTER <conditions>]), <min>, <max>, true, true) |
arr[? NONE FILTER <conditions>] | LENGTH(arr[* FILTER <conditions>]) == 0 |
arr[? ANY FILTER <conditions>] | LENGTH(arr[* FILTER <conditions>]) > 0 |
arr[? ALL FILTER <conditions>] | LENGTH(arr[* FILTER <conditions>]) == LENGTH(arr) |
arr[? AT LEAST (<number>) FILTER <conditions>] | LENGTH(arr[* FILTER <conditions>]) >= <number> |
arr[?] | LENGTH(arr[*]) > 0 |