Операторы массива¶
Расширение массива¶
Чтобы легко получить доступ к именованному атрибуту из всех элементов массива, 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
)ANY
ALL
AT 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 |