【问题标题】:What is the proper way to use IF THEN in AQL?在 AQL 中使用 IF THEN 的正确方法是什么?
【发布时间】:2019-02-05 02:46:43
【问题描述】:

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

【问题讨论】:

  • 如果语法错误指向特定位置,而您没有在问题中报告,您希望我们如何给出有针对性的回复?您能否编辑问题并将确切的错误消息以及它提供的任何周围上下文复制粘贴到其中?
  • 没有周围的上下文,但我会编辑问题。
  • 嗯,天哪,我完全错过了你的第一个三元组......这对我来说真的很糟糕,因为这显然是所有这一切的重点。如果这完全可行,您需要在第一个 ? 及其匹配的 : 之间用括号括起来,因为没有任何优先规则可以让您在没有帮助的情况下这样做。但是,我更倾向于认为这是他们希望您使用相关的 arangojs 语言来执行该逻辑的事情。
  • 对我来说似乎很奇怪,一种类似于 SQL 的语言无法像使用 SQL 那样做 IF THEN。这对语言的可用性造成了相当大的打击。

标签: conditional-statements arangodb upsert aql arangojs


【解决方案1】:

三元运算符不能像 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() 返回null,因此doc._key 也是@ 987654343@,导致_key: null - 无效。

【讨论】:

  • 一旦我纠正了你的“xb”错别字,这就会奏效,谢谢!
  • 已更正,并添加了我添加 PARSE_IDENTIFIER() 的更多详细信息。
  • 实际上,文档键是唯一的输入,这对我来说含糊不清是不好的,但上面的 AQL 是我在将它与 arangojs 一起使用之前试图让查询在 arangosh 中工作。集合名称也是预设的,所以我可以安全地做到这一点,而无需像 PARSE_IDENTIFIER() 这样的任何东西。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 2013-06-26
  • 1970-01-01
  • 2011-01-24
  • 2020-09-14
  • 1970-01-01
  • 2015-12-22
相关资源
最近更新 更多