Запросы данных¶
Существует два основных типа запросов AQL:
- запросы, которые обращаются к данным (читают документы)
- запросы, которые изменяют данные (создают, обновляют, заменяют, удаляют документы)
Запросы доступа к данным¶
Извлечение данных из базы данных с помощью AQL всегда включает операцию RETURN
. Его можно использовать для возврата статического значения, например строки:
1 |
|
Результатом запроса всегда является массив элементов, даже если был возвращен один элемент, и в этом случае он содержит один элемент: ["Hello ArangoDB!"]
.
Функцию DOCUMENT()
можно вызвать для получения одного документа через его дескриптор документа, например:
1 |
|
RETURN
обычно сопровождается циклом FOR
для перебора документов коллекции. Следующий запрос выполняет тело цикла для всех документов коллекции, называемой пользователями. В этом примере каждый документ возвращается без изменений:
1 2 |
|
Вместо того, чтобы возвращать необработанный документ, можно легко создать проекцию:
1 2 |
|
Для каждого пользовательского документа возвращается объект с двумя атрибутами. Значением атрибута user
установлено содержимое пользовательского документа, а newAttribute
— это статический атрибут с логическим значением true
.
В тело цикла можно добавить такие операции, как FILTER
, SORT
и LIMIT
, чтобы сузить и упорядочить результат. Вместо показанного выше вызова DOCUMENT()
можно также получить документ, который описывает пользователя phil
следующим образом:
1 2 3 |
|
В этом примере используется ключ документа, но любой другой атрибут может также использоваться для фильтрации. Поскольку ключ документа гарантированно уникален, этому фильтру может соответствовать не более одного документа. Для других атрибутов это может быть не так. Чтобы вернуть подмножество активных пользователей (определяемых атрибутом, называемым status
), отсортированных по имени в порядке возрастания, вы можете сделать:
1 2 3 4 |
|
Обратите внимание, что операции не обязательно должны выполняться в фиксированном порядке и что их порядок может существенно повлиять на результат. Ограничение количества документов перед фильтром, как правило, не то, что вам нужно, потому что оно легко упускает множество документов, которые удовлетворяют критерию фильтра, но игнорируются из-за преждевременного предложения LIMIT
. По вышеупомянутым причинам LIMIT
обычно ставится в самом конце, после FILTER
, SORT
и других операций.
См. «Операции высокого уровня» для получения более подробной информации.
Запросы на изменение данных¶
AQL поддерживает следующие операции модификации данных:
- INSERT: вставлять новые документы в коллекцию
- UPDATE: частично обновить существующие документы в коллекции
- REPLACE: полностью заменить существующие документы в коллекции
- REMOVE: удалить существующие документы из коллекции
- UPSERT: условно вставить или обновить документы в коллекции
Вы можете использовать их для изменения данных одного или нескольких документов с помощью одного запроса. Это лучше, чем выборка и обновление документов по отдельности с помощью нескольких запросов. Однако, если необходимо изменить только один документ, специализированные операции модификации данных ArangoDB для отдельных документов могут выполняться быстрее.
Ниже вы найдете несколько простых примеров запросов, в которых используются эти операции. Операции подробно описаны в главе «Операции высокого уровня».
Изменение одного документа¶
Начнем с основ: операции INSERT
, UPDATE
и REMOVE
для отдельных документов. Вот пример, который вставляет документ в коллекцию users
с помощью операции INSERT
:
1 2 3 4 5 |
|
Коллекция должна существовать до выполнения запроса. Запросы AQL не могут создавать коллекции.
Если вы запустите приведенный выше запрос, результатом будет пустой массив, потому что мы не указали, что возвращать, используя ключевое слово RETURN
. Это необязательно в запросах на изменение, но обязательно в запросах на доступ к данным. Несмотря на пустой результат, приведенный выше запрос по-прежнему создает новый пользовательский документ.
Вы можете предоставить ключ для нового документа; если он не указан, ArangoDB создаст его для вас.
1 2 3 4 5 6 |
|
Поскольку ArangoDB не содержит схем, атрибуты документов могут различаться:
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 |
|
Операция UPDATE
позволяет добавлять или изменять атрибуты существующих документов. Следующий запрос изменяет ранее созданного пользователя, изменяя атрибут status
и добавляя атрибут location
:
1 2 3 4 |
|
Операция REPLACE
является альтернативой операции UPDATE
, которая позволяет заменить все атрибуты документа (кроме атрибутов, которые нельзя изменить, например _key
):
1 2 3 4 5 6 7 |
|
Вы можете удалить документ с помощью операции REMOVE
, требуя только ключ документа для его идентификации:
1 |
|
Изменение нескольких документов¶
Операции модификации данных обычно сочетаются с циклами FOR
для перебора заданного списка документов. При желании их можно комбинировать с операторами FILTER
и т. п.
Чтобы создать несколько новых документов, используйте операцию INSERT
вместе с FOR
. Вы также можете использовать INSERT
для создания копий существующих документов из других коллекций или для создания синтетических документов (например, в целях тестирования). Следующий запрос создает 1000 тестовых пользователей с некоторыми атрибутами и сохраняет их в коллекции users
:
1 2 3 4 5 6 7 8 9 |
|
Давайте изменим существующие документы, соответствующие некоторому условию:
1 2 3 |
|
Вы также можете обновить существующие атрибуты на основе их предыдущего значения:
1 2 3 |
|
Приведенный выше запрос работает только в том случае, если в документе уже присутствует атрибут numberOfLogins
. Если неясно, есть ли в документе атрибут numberOfLogins
, увеличение необходимо сделать условным:
1 2 3 4 5 |
|
Обновления нескольких атрибутов могут быть объединены в один запрос:
1 2 3 4 5 6 |
|
Обратите внимание, что запрос на обновление может завершиться ошибкой во время выполнения, например, из-за того, что документ, который нужно обновить, не существует. В этом случае запрос прерывается при первой ошибке. В режиме одного сервера все изменения, сделанные запросом, откатываются, как если бы они никогда не происходили.
Вы можете копировать документы из одной коллекции в другую, читая из одной коллекции и записывая в другую. Скопируем содержимое коллекции users
в коллекцию backup
:
1 2 |
|
Обратите внимание, что обе коллекции должны уже существовать на момент выполнения запроса. Запрос может завершиться ошибкой, если коллекция backup
уже содержит документы, так как выполнение вставки может попытаться снова вставить тот же документ (определяемый атрибутом _key
). Это вызывает нарушение ограничения уникального ключа и прерывает запрос. В режиме одного сервера все изменения, сделанные запросом, также откатываются. Чтобы такая операция копирования работала во всех случаях, целевую коллекцию можно предварительно очистить, используя запрос REMOVE
или усекая ее другими способами.
Чтобы не просто частично обновить, а полностью заменить существующие документы, воспользуйтесь операцией REPLACE
. Следующий запрос заменяет все документы в коллекции backup
документами, найденными в коллекции users
. Документы, общие для обоих сборников, заменены. Все остальные документы остаются без изменений. Документы сравниваются по их атрибутам _key
:
1 2 |
|
Приведенный выше запрос завершается ошибкой, если в коллекции users
есть документы, которых еще нет в коллекции backup
. В этом случае запрос попытается заменить несуществующие документы. Если такой случай обнаруживается при выполнении запроса, запрос прерывается. В режиме одного сервера все изменения, сделанные запросом, откатываются.
Чтобы сделать запрос успешным независимо от ошибок, используйте опцию запроса ignoreErrors
:
1 2 |
|
Это продолжает выполнение запроса, если во время операции REPLACE
, UPDATE
, INSERT
или REMOVE
возникают ошибки.
Наконец, давайте найдем несколько документов в коллекции users
и удалим их из коллекции backup
. Связь между документами в обеих коллекциях устанавливается через ключи документов:
1 2 3 |
|
В следующем примере удаляются все документы как из users
, так и из backup
:
1 2 3 |
|
Изменение подструктур¶
Чтобы изменить списки в документах, например, чтобы обновить определенные атрибуты объектов в массиве, вы можете вычислить новый массив, а затем обновить соответствующий атрибут документа. Это может включать использование подзапросов и временных переменных.
Создайте коллекцию с именем complexCollection
и выполните следующий запрос:
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 28 |
|
Следующий запрос обновляет атрибут верхнего уровня документов subList
. Значения attributeToAlter
во вложенном объекте изменяются, если соседний атрибут filterByMe
имеет значение true
:
1 2 3 4 5 6 7 8 9 |
|
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 28 29 30 31 32 33 34 |
|
Чтобы повысить производительность запроса, вы можете обновлять документы только в том случае, если в subList
есть изменения, которые необходимо сохранить. Вместо непосредственного сравнения текущего и измененного списка вы можете сравнить их хеш-значения с помощью функции HASH()
, которая работает быстрее для больших объектов и массивов. Вы также можете заменить подзапрос встроенным выражением:
1 2 3 4 5 6 7 8 9 |
|
Возвращаемые документы¶
Запросы на изменение данных могут дополнительно возвращать документы. Чтобы сослаться на вставленные, удаленные или измененные документы в операторе RETURN
, операторы модификации данных вводят псевдозначения OLD
и/или NEW
:
1 2 3 |
|
1 2 3 4 |
|
1 2 3 4 |
|
NEW
относится к вставленной или измененной версии документа, а OLD
относится к версии документа перед обновлением или удалением. Операторы INSERT
могут ссылаться только на псевдозначение NEW
, а операции REMOVE
— только на OLD
. UPDATE
, REPLACE
и UPSE`RT могут относиться к любому из них.
Во всех случаях возвращаются полные документы со всеми их атрибутами, включая потенциально автоматически сгенерированные атрибуты, такие как _id
, _key
и _rev
, и атрибуты, не указанные в выражении частичного обновления.
Проекции документов OLD и NEW¶
Можно вернуть проекцию документов OLD
или NEW
вместо возврата всего документа. Это можно использовать для уменьшения количества данных, возвращаемых запросами.
Например, следующий запрос возвращает только ключи вставленных документов:
1 2 3 |
|
Использование OLD и NEW в одном запросе¶
Для операций UPDATE
, REPLACE
и UPSERT
можно использовать как OLD
, так и NEW
, чтобы вернуть предыдущую версию документа вместе с обновленной версией:
1 2 3 4 |
|
Вычисления в OLD или NEW¶
Также можно выполнить дополнительные вычисления с операторами LET
между частью изменения данных и окончательным RETURN
запроса AQL. Например, следующий запрос выполняет операцию upsert
и возвращает информацию о том, был ли обновлен существующий документ или вставлен новый документ. Он делает это, проверяя переменную OLD
после UPSERT
и используя оператор LET
для сохранения временной строки для типа операции:
1 2 3 4 5 |
|
Ограничения¶
Имя измененной коллекции (users
и backup
в приведенных выше случаях) должно быть известно исполнителю AQL во время компиляции запроса и не может изменяться во время выполнения. Допускается использование параметра привязки для указания имени коллекции.
Невозможно использовать несколько операций модификации данных для одной и той же коллекции в одном запросе или выполнять операцию модификации данных для определенной коллекции операцией чтения для той же коллекции. Также невозможно выполнить какую-либо операцию модификации данных с помощью запроса обхода (который может считывать из произвольных коллекций, не обязательно известных в начале обхода).
Это означает, что вы не можете помещать несколько операторов REMOVE
или UPDATE
для одной и той же коллекции в один и тот же запрос. Однако можно изменять разные коллекции, используя несколько операций модификации данных для разных коллекций в одном запросе. Если у вас есть запрос с несколькими местами, в котором необходимо удалить документы из одной коллекции, рекомендуется собрать эти документы или их ключи в массив и удалить документы из этого массива с помощью одной операции REMOVE
.
За операциями модификации данных могут дополнительно следовать операции LET
для выполнения дальнейших вычислений и операция RETURN
для возврата данных.
Транзакционное исполнение¶
На одном сервере операции модификации данных выполняются транзакционно. В случае сбоя операции модификации данных любые сделанные ею изменения автоматически откатываются, как будто их никогда и не было.
Если используется механизм RocksDB и включены промежуточные фиксации, запрос может выполнять промежуточные фиксации транзакций в случае, если текущая транзакция (запрос AQL) достигает заданных пороговых значений размера. В этом случае операции запроса, выполненные до сих пор, фиксируются и не откатываются в случае последующего прерывания/отката. Это поведение можно контролировать, настраивая параметры промежуточной фиксации для механизма RocksDB.
В кластере запросы модификации данных AQL не выполняются транзакционно. Кроме того, запросы AQL с операциями UPDATE
, REPLACE
, UPSERT
или REMOVE
требуют указания атрибута _key
для всех документов, которые должны быть изменены или удалены, даже если для коллекции выбран атрибут ключа сегмента, отличный от _key
.