【问题标题】:ArangoDB AQL: Update single object in embedded arrayArangoDB AQL:更新嵌入式数组中的单个对象
【发布时间】:2015-03-17 17:21:09
【问题描述】:

我正在尝试使用 AQL 更新嵌入式数组中 json 文档的属性。如何使用下面的 AQL 更新“家庭”类型地址的“地址行”?

用户:

{
name: "test",
address: [
      {"addressline": "1234 superway", type:"home"}, 
      {"addressline": "5678 superway", type:"work"}
     ]
}

到目前为止的 AQL 尝试

for u in users
   for a in u.address
     FILTER a.type='home'
       UPDATE u WITH {<What goes here to update addressline?>} in users

感谢您的帮助。

问候, 安詹

【问题讨论】:

    标签: arangodb


    【解决方案1】:

    为此,我们必须使用临时变量。我们将在那里收集子列表并进行更改。我们选择一个简单的布尔过滤条件来使查询更易于理解。

    首先让我们创建一个包含样本的集合:

    database = db._create('complexCollection')
    database.save({ 
      "topLevelAttribute" : "a", 
      "subList" : [ 
        { 
          "attributeToAlter" : "oldValue", 
          "filterByMe" : true 
        }, 
        { 
          "attributeToAlter" : "moreOldValues", 
          "filterByMe" : true 
        }, 
        { 
          "attributeToAlter" : "unchangedValue", 
          "filterByMe" : false 
        } 
      ] 
    })
    

    这是将 subList 保留在 alteredList 上以便稍后更新的查询:

    FOR document in complexCollection
      LET alteredList = (
        FOR element IN document.subList 
           LET newItem = (! element.filterByMe ?
                          element :
                          MERGE(element, { attributeToAlter: "shiny New Value" }))
           RETURN newItem)
      UPDATE document WITH { subList:  alteredList } IN complexCollection
    

    虽然查询现在可以正常工作:

    db.complexCollection.toArray()
    [ 
      { 
        "_id" : "complexCollection/392671569467", 
        "_key" : "392671569467", 
        "_rev" : "392799430203", 
        "topLevelAttribute" : "a", 
        "subList" : [ 
          { 
            "filterByMe" : true, 
            "attributeToAlter" : "shiny New Value" 
          }, 
          { 
            "filterByMe" : true, 
            "attributeToAlter" : "shiny New Value" 
          }, 
          { 
            "filterByMe" : false, 
            "attributeToAlter" : "unchangedValue" 
          } 
        ] 
      } 
    ]
    

    这个查询很快就会成为性能瓶颈,因为它修改集合中的所有文档无论值是否改变。因此,如果我们真的改变了文档的值,我们只想更新文档。因此我们使用第二个 FOR 来测试 subList 是否会被改变:

    FOR document in complexCollection
      LET willUpdateDocument = (
        FOR element IN document.subList 
          FILTER element.filterByMe LIMIT 1 RETURN 1)
    
      FILTER LENGTH(willUpdateDocument) > 0
    
      LET alteredList = (
        FOR element IN document.subList 
           LET newItem = (! element.filterByMe ?
                          element :
                          MERGE(element, { attributeToAlter: "shiny New Value" }))
           RETURN newItem)
    
      UPDATE document WITH { subList:  alteredList } IN complexCollection
    

    【讨论】:

    • 谢谢@dothebart!这很棒!我知道整个子列表可能必须在更新/合并中传递,但正在努力设置该子列表。再次感谢。
    【解决方案2】:

    ArangoDB 现在支持子集索引。以下查询基于dothebarts 的回答:

    FOR document IN complexCollection
        FILTER document.subList[*].filterByMe == true LIMIT 1
        UPDATE document WITH {
            items: (
                FOR element IN document.subList
                    RETURN element.filterByMe == true
                         ? MERGE(element, { attributeToAlter: "the shiniest value"})
                         : element
            )
        } IN complexCollection
    

    注意:不要忘记在subList[*].filterByMe 上创建一个hash 索引:

    db._collection('complexCollection')
        .ensureIndex({type:'hash',fields:['subList[*].filterByMe']});
    

    【讨论】:

      猜你喜欢
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 2021-11-05
      相关资源
      最近更新 更多