【问题标题】:ArangoDB array query for an arrayArangoDB 数组查询数组
【发布时间】:2021-09-11 15:24:20
【问题描述】:

我正在尝试在 arangodb 中编写一个更新命令,以在具有嵌套数组的文档中插入单个“key”:“value”属性。

{
  "OuterBlock": {
    "InnerBlock": {
      "key1": "value1",
      "key2": {
        "key21": "value21"
      },
      "key3": {
        "key31": "value31"
      },
      "key4": [
        {
          "key41": "value1",
          "key42": {
            "key421": "value421"
          },
          "key43": [
            {
              "key431": "value431",
              "key432": {
                "key4321": "value4321"
              }
            }
          ]
        },
        {
          "key44": "value44",
          "key45": {
            "key451": "key451"
          }
        }
      ]
    }
  }
}

我需要在 key432 下再添加一个 key:value 对(例如:“key4322”:“value4322”)。我先尝试了选择查询,然后尝试使用 MERGE 命令添加此属性。

FOR t IN test 
FILTER t._key=="Test"
Collect a = t.OuterBlock.InnerBlock.key4[0].key43[0].key432 into aitems
LET newa = (MERGE(a , {"key4322": "value4322"}))
RETURN newa

返回结果如下

[
  {
    "key4321": "value4321",
    "key4322": "value4322"
  }
]

所以我尝试使用以下查询将此结果与第一个块“key43”合并

FOR t IN test
FILTER t._key=="Test"
collect a = t.OuterBlock.InnerBlock.key4[0].key43[0]  into aitems
LET newa = (MERGE(a , {key432: 
(
FOR t IN test 
FILTER t._key=="Test"
Collect b = t.OuterBlock.InnerBlock.key4[0].key43[0].key432 into bitems
LET newb = (MERGE(b , {"key4322": "value4322"}))
Return newb
)
}))
RETURN newa

输出在 key432 中给了我一个额外的数组块 [],它在原始数据中不存在。因此它正在改变文档的格式。我怎样才能删除这个数组块。 请提出建议。

[
  {
    "key431": "value431",
    "key432": **[**
      {
        "key4321": "value4321",
        "key4322": "value4322"
      }
    **]**
  }
]

【问题讨论】:

  • 请帮忙,因为我在这个数组上苦苦挣扎了几天。尝试使用 PUSH 但没有运气 :( 由于检索查询不起作用,我离此要求的更新语句不远

标签: arangodb aql


【解决方案1】:

您需要逐步替换数组元素并合并对象,因为 AQL 中的变量是不可变的。在客户端扩展嵌套对象然后在服务器端替换整个文档会更容易。尽管如此,这在 AQL 中是可能的:

FOR t IN test
  FILTER t._key == "test"
  LET key432 = MERGE(
    t.OuterBlock.InnerBlock.key4[0].key43[0].key432,
    { key4322: "value4322" }
  )
  LET key43 = REPLACE_NTH(
    t.OuterBlock.InnerBlock.key4[0].key43, 0,
    MERGE(t.OuterBlock.InnerBlock.key4[0].key43[0], { key432 })
  )
  LET key4 = REPLACE_NTH(t.OuterBlock.InnerBlock.key4, 0,
    MERGE(t.OuterBlock.InnerBlock.key4[0], { key43 })
  )
  RETURN MERGE_RECURSIVE(t, { OuterBlock: { InnerBlock: { key4 } } })

结果:

[
  {
    "OuterBlock": {
      "InnerBlock": {
        "key1": "value1",
        "key2": {
          "key21": "value21"
        },
        "key3": {
          "key31": "value31"
        },
        "key4": [
          {
            "key41": "value1",
            "key42": {
              "key421": "value421"
            },
            "key43": [
              {
                "key431": "value431",
                "key432": {
                  "key4321": "value4321",
                  "key4322": "value4322"
                }
              }
            ]
          },
          {
            "key44": "value44",
            "key45": {
              "key451": "key451"
            }
          }
        ]
      }
    }
  }
]

关于额外的数组,请记住子查询总是返回一个数组,就像顶级查询一样。

LET newa = (MERGE(a , {key432: 
(
FOR t IN test ... // subquery
)

要仅获取子查询返回的第一个元素,您可以使用FIRST( FOR ... )( FOR ... )[0]

【讨论】:

  • 非常感谢您的回复。我会检查这个查询。有一个疑问——你能否再解释一下这一行——“在客户端扩展嵌套对象然后在服务器端替换整个文档会更容易。”
  • AQL 不允许您就地更改变量,但您可以在例如像 doc.OuterBlock.InnerBlock.key4[0].key43[0].key432.key4322 = "value4322" 这样的 JavaScript。因此修改数据结构变得更加容易。然后您需要用修改后的文档替换原始文档,例如在 AQL 中使用 REPLACE { ... } IN test。您可以使用 arangojs 在客户端实现这一点,但您也可以在 JavaScript 中编写自己的 AQL 函数来返回修改后的文档:arangodb.com/docs/stable/aql/extending.html
  • 我无法使用 replace_nth,因为我使用的是较低版本的 arango 数据库
  • 因为它在这两种情况下都是第一个元素,您可以使用UNSHIFT(SHIFT(t.OuterBlock.InnerBlock.key4[0].key43), MERGE(...))UNSHIFT(SHIFT(t.OuterBlock.InnerBlock.key4), MERGE(...)) 代替。任何职位的通用解决方案是(FOR i IN 0..LENGTH(<array>)-1 RETURN i == <pos> ? <new-value> : <array>[i])
  • 请注意,REPLACE_NTH() 是在 v3.7.0 和 v3.6 支持中引入的,支持将于下个月(2021 年 8 月结束)结束。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多