首页 > 解决方案 > 在 AQL 中使用 IF THEN 的正确方法是什么?

问题描述

我正在尝试使用 IF THEN 样式的 AQL,但我可以在 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)

标签: conditional-statementsarangodbupsertaqlarangojs

解决方案


三元运算符不能像 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

我添加_keyINSERT,否则文档将获得一个自动生成的密钥,这似乎不是预期的。使用FOR循环和 a 的FILTER行为类似于 IF 构造(没有 ELSE)。因为这是一个数据修改查询,所以没有必要显式地显示RETURN任何内容,并且在您的原始查询RETURN null中无论如何都需要针对 ELSE 情况。如果您尝试快速连续执行查询并且没有更新或插入任何内容,那么您的结果会产生(真正的空结果)[ null ][ ]

请注意,必须使用PARSE_IDENTIFIER()从文档 ID 字符串中获取密钥并执行INSERT { _key: key }. 在插入的情况下,INSERT { _key: doc._key }您会遇到一个无效的文档键错误,因为如果没有文档xp/a-b,则DOCUMENT()返回null并且doc._key因此也是null,导致_key: null- 无效。


推荐阅读