ArangoDB AQL:更新嵌入式阵列中的单个对象

Anj*_*Rao 9 arangodb

我试图使用AQL更新嵌入式数组中的json文档的属性.如何使用下面的AQL更新"home"类型地址的"地址线"?

用户:

{
name: "test",
address: [
      {"addressline": "1234 superway", type:"home"}, 
      {"addressline": "5678 superway", type:"work"}
     ]
}
Run Code Online (Sandbox Code Playgroud)

到目前为止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
Run Code Online (Sandbox Code Playgroud)

感谢您的帮助.

此致,Anjan

dot*_*art 9

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

首先,我们使用示例创建一个集合:

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

其继承人保持查询子列表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
Run Code Online (Sandbox Code Playgroud)

虽然现在的查询功能正常:

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" 
      } 
    ] 
  } 
]
Run Code Online (Sandbox Code Playgroud)

此查询可能很快就会成为性能瓶颈,因为无论值是否发生变化,它都会修改集合中的所有文档.因此,如果我们确实更改了它们的值,我们只想更新文档.因此,我们使用第二个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
Run Code Online (Sandbox Code Playgroud)


Rie*_*u͢s 6

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

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

    UPDATE document WITH { items:alteredList } IN complexCollection
Run Code Online (Sandbox Code Playgroud)

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

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