To do this, we need to work with temporary variables. We will collect a sublist there and change it. We choose the condition of a simple Boolean filter to make the query more understandable.
First, create a collection with a sample:
database = db._create('complexCollection') database.save({ "topLevelAttribute" : "a", "subList" : [ { "attributeToAlter" : "oldValue", "filterByMe" : true }, { "attributeToAlter" : "moreOldValues", "filterByMe" : true }, { "attributeToAlter" : "unchangedValue", "filterByMe" : false } ] })
Heres the Query, which saves the sublist in the altertered file to update it later:
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
As long as the request is, it now works:
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" } ] } ]
This query is likely to become a performance bottleneck soon, as it modifies all the documents in the collection whether the values โโare changed or not . Therefore, we only want to UPDATE documents if we really change their cost. Therefore, we use the second FOR to check whether the sublist will be changed or not:
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