在 AQL 中使用 IF THEN 的正确方法是什么?

What is the proper way to use IF THEN in AQL?

我正在尝试使用 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)

三元运算符不能像 if/else 结构那样使用,以供尝试。它适用于您用来计算 mult 的条件(子)表达式。它不能单独存在,如果你把它写成一个 if 表达式,它就不能被返回或赋值。

此外,它需要大括号,但实际问题是正文包含 LETUPSERTRETURN 等操作。这些是不能在表达式内部使用的语言结构。

如果我没理解错的话,你想要:

  • 如果集合 xb
  • 中不存在具有键 a-b 的文档,则插入一个新文档
  • 如果确实存在,则更新它,但前提是最后一次更新是在 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()从文档ID字符串中获取密钥并执行INSERT { _key: key }。使用 INSERT { _key: doc._key } 你会 运行 在插入案例中出现 无效文档键 错误,因为如果没有文档 xp/a-bDOCUMENT() returns nulldoc._key 因此也是 null,导致 _key: null - 这是无效的。