Как правильно использовать IF THEN в AQL?
Я пытаюсь использовать AQL в стиле IF THEN, но единственным соответствующим оператором, который я смог найти в документации по AQL, был троичный оператор. Я пытался добавить синтаксис IF THEN к моему уже работающему AQL, но он выдает синтаксические ошибки независимо от того, что я пытаюсь сделать.
LET doc = DOCUMENT('xp/a-b')
LET now = DATE_NOW()
doc == null || now - doc.last >= 45e3 ?
LET mult = (doc == null || now - doc.last >= 6e5 ? 1 : doc.multiplier)
LET gained = FLOOR((RAND() * 3 + 3) * mult)
UPSERT {_key: 'a-b'}
INSERT {
amount: gained,
total: gained,
multiplier: 1.1,
last: now
}
UPDATE {
amount: doc.amount + gained,
total: doc.total + gained,
multiplier: (mult < 4 ? FLOOR((mult + 0.1) * 10) / 10 : 4),
last: now
}
IN xp
RETURN NEW
:
RETURN null
Выдает следующее сообщение об ошибке:
stacktrace: ArangoError: AQL: syntax error, unexpected identifier near 'doc == null || now - doc.last >=...' at position 1:51 (while parsing)
1 ответ
Тернарный оператор не может использоваться как конструкция if/else так, как пытался. Это для условных (под) выражений, которые вы используете для вычисления mult
, Он не может стоять сам по себе, ничто не может быть возвращено или назначено, если вы напишите это как выражение if.
Более того, для этого потребуются фигурные скобки, но проблема в том, что тело содержит такие операции, как LET
, UPSERT
а также RETURN
, Это языковые конструкции, которые нельзя использовать внутри выражений.
Если я правильно понимаю, вы хотите:
- вставить новый документ, если нет документа с ключом
a-b
существует еще в коллекцииxb
- если он существует, то обновите его, но только если последнее обновление было 45 секунд или дольше назад
Работает ли у вас следующий запрос?
FOR id IN [ 'xp/a-b' ]
LET doc = DOCUMENT(id)
LET key = PARSE_IDENTIFIER(id).key
LET now = DATE_NOW()
FILTER doc == null || now - doc.last >= 45e3
LET mult = (doc == null || now - doc.last >= 6e5 ? 1 : doc.multiplier)
LET gained = FLOOR((RAND() * 3 + 3) * mult)
UPSERT { _key: key }
INSERT {
_key: key,
amount: gained,
total: gained,
multiplier: 1.1,
last: now
}
UPDATE {
amount: doc.amount + gained,
total: doc.total + gained,
multiplier: (mult < 4 ? FLOOR((mult + 0.1) * 10) / 10 : 4),
last: now
}
IN xp
RETURN NEW
я добавил _key
в INSERT
в противном случае документ получит автоматически сгенерированный ключ, который, по-видимому, не предназначен. Используя FOR
петля и FILTER
действует как конструкция IF (без ELSE). Поскольку это запрос на изменение данных, нет необходимости явно RETURN
что-нибудь и в исходном запросе вы RETURN null
в любом случае. В то время как ваш приведет к [ null ]
Мое производит [ ]
(действительно пустой результат), если вы попытаетесь выполнить запрос в быстрой последовательности и ничего не будет обновлено или вставлено.
Обратите внимание, что необходимо использовать PARSE_IDENTIFIER()
получить ключ из строки идентификатора документа и сделать INSERT { _key: key }
, С INSERT { _key: doc._key }
вы столкнетесь с ошибкой неверного ключа документа в случае вставки, потому что если нет документа xp/a-b
, DOCUMENT()
возвращается null
а также doc._key
поэтому также null
, что приводит к _key: null
- который является недействительным.