在Arangodb中如何在单个for循环中进行多重upsert

时间:2017-04-05 10:35:42

标签: arangodb aql

我希望同时运行upsert

for i in [1,2]
upsert { _key: i } insert {v:i} update{} in Test
upsert { _key: i*100 } insert {v:i*100} update{} in Test

但我得到了

Query: variable '$OLD' is assigned multiple times (while parsing)

版本:3.1.14

修改

在真实查询中,我想要做的就是这样的

FOR n IN MyData
FILTER n.person
    FOR p IN n.person
    UPSERT { _key: p.id } INSERT { _key:p.id, name:p.name} UPDATE {} IN Person
    UPSERT { _from:CONCAT('Person/',p.id),_to:CONCAT('Other/',n.id) }
    INSERT { _from:CONCAT('Person/',p.id),_to:CONCAT('Other/',n.id), type: n.type }  
    UPDATE {} IN PersonRelation

有没有arangodb认为会有多重upsert?

目前,我必须逐个运行查询,数据集很大,因此,只运行一次upsert很慢。也许我应该使用INSERTignoreErrors

1 个答案:

答案 0 :(得分:1)

我非常确定会发生此错误,因为您正在向该集合写入两次,并且查询优化程序不会让您这样做。

另一种解决方案是使用UPSERT命令编写相同的内容,但是稍微改变一下,这样你只需编写一次。

此示例有效:

LET new_documents = FLATTEN(FOR i IN [1,2] RETURN [{_key: TO_STRING(i), v:i},{ _key: TO_STRING(i*100), v:i*100 } ])
FOR doc IN new_documents
    UPSERT { _key: doc._key } INSERT { _key: doc._key, v: doc.v } UPDATE{} IN Test
    RETURN {
        new_entries: NEW,
        old_entries: OLD
   }

一些注意事项:

  • 创建new_documents变量,它包含您要添加的记录。
  • new_documents的结果通过FLATTEN将其转换为平面对象数组。
  • 每个文档的_key都会转换为字符串,因为_key必须是字符串
  • 然后遍历该展平的数组,并对数组的每个成员执行UPSERT
  • 访问输出变量NEWOLD,它们是UPSERT命令中的空闲输出变量。

如果您要插入新记录并且自动生成NEW值,则_key变量非常有用。通过查看NEW变量,您可以获取刚添加的所有新文档的_key,如果您添加它们的话。

更新

为了支持您更新的问题,您仍然可以通过在变量定义中隔离它们来执行多个UPSERT,如下所示:

FOR n IN myData
FILTER n.v
    LET test = (UPSERT { _key: n.v } INSERT { _key: n.v, v: n.v } UPDATE {} IN Test)
    LET test2 = (UPSERT { _key: n.v } INSERT { _key: n.v, v: n.v } UPDATE {} IN Test2)
    RETURN {
        done: true
    }

此查询从myData读取文档,然后根据该文档执行UPSERTTest集合中的Test2命令。

这应该可以帮助您处理数据模型,只需确保您用作新文档的_key的值是一个字符串。