Как правильно использовать IF THEN в AQL? - PullRequest
0 голосов
/ 05 февраля 2019

Я пытаюсь использовать 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 Ответ

0 голосов
/ 05 февраля 2019

Тернарный оператор не может использоваться как конструкция if / else в способе try.Это для условных (под) выражений, которые вы используете для вычисления 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 для случая ELSE.В то время как ваш результат будет [ null ], мой выдает [ ] (действительно пустой результат), если вы попытаетесь выполнить запрос в быстрой последовательности и ничего не будет обновлено или вставлено.

Обратите внимание, что необходимо использовать PARSE_IDENTIFIER() чтобы получить ключ из строки идентификатора документа и выполните INSERT { _key: key }INSERT { _key: doc._key } вы можете столкнуться с ошибкой неверного ключа документа в случае вставки, потому что если документа нет xp/a-b, DOCUMENT() возвращает null и, следовательно, doc._key также null, что приводит к _key: null - что неверно.

...