arangodb / arangojs

The official ArangoDB JavaScript driver.
https://arangodb.github.io/arangojs
Apache License 2.0
601 stars 107 forks source link

Update item in document array #652

Closed noahehall closed 4 years ago

noahehall commented 4 years ago

hello arangotans

playing on the solution to this issue

problem: update an item, in an array, on a document error: ArangoError: AQL: collection or array expected as operand to FOR loop; you provided a value of type 'null'

sample document:

 {
   key: jordan_greenhall,
   music: [
     { id: 2pac },
     {id: nipsey},
     {id; mozzy}
   ]
}

query throwing error

   aql`
          LET doc = DOCUMENT(${collectionName}/${thisDocKey})
          let itemId = ${itemId}
          let obj = ${obj}
          let prop = ${prop}
          let updated = (
            FOR item in doc[prop]
            FILTER item.id == itemId
            return MERGE(item, obj)
          )
          UPDATE doc WITH { [prop]: updated} in ${db.collection(collectionName)}
          RETURN doc

        `

obviously its an error with arango, and not my query ;)

noahehall commented 4 years ago

this indeed works in directly in the arango web interface query thing

LET doc = DOCUMENT("Paths/account-collectors")
let itemId = 'base'
let obj = { wtf: 'yo' }
let prop = 'strategies'

let updated = (
FOR item in doc[prop]
FILTER item.id == itemId
return MERGE(item, obj)
)
UPDATE doc WITH { [prop]: updated} in 'Paths'
RETURN doc

but fails when I use the node arango thing

noahehall commented 4 years ago

if anyone else arrives here thinking wtf the solution was definitely thinking about the returned error.

in node you have to declare the variables within the aql template

working query:

aql`
          let colName = ${collectionName} // <---
          let key = ${thisDocKey} // <---
          LET doc = DOCUMENT(colName,key) // <---
          let itemId = ${itemId}
          let obj = ${obj}
          let prop = ${prop}

          let updated = (
            FOR item in doc[prop]
            FILTER item.id == itemId
            return MERGE(item, obj)
          )
          UPDATE doc WITH { [prop]: updated} in ${db.collection(collectionName)}
          RETURN doc

        `
noahehall commented 4 years ago

is there a better way to do what im doing here? e.g.

also intriguingly this works elseware in my file

RETURN UNSET(DOCUMENT("${collectionName}/${thisDocKey}"), "_key", "_id", "_rev")

Why do I have to use the intermediate variables when doing the loop?

noahehall commented 4 years ago

@jsteemann ^^

noahehall commented 4 years ago

ps, always return NEW mf

noahehall commented 4 years ago

ps read this https://www.arangodb.com/docs/3.6/aql/examples-data-modification-queries.html

in the loop you have to check each item MERGE only the matching item, else you'll rewrite the entire prop