简体   繁体   中英

I can not update same document multiple times in FOR loop in ArangoDB

I have a collection or users and I need to update the property "cuantity" twice in a loop. For example in the update array I need to to increase it by 1 and then increase it by 2, so if the actual value is 1 the result value must be 4,but it does not happen this way. ArangoDB seams to take the last update object in the update array loop and dismiss the previous update objects in the loop.

This is my collection (for make testing simple):

{"_key": "1", "name":"ivan", "cuantity":1}
{"_key": "2", "name":"juan", "cuantity":1}
{"_key": "3", "name":"carl", "cuantity":1}

This is my query and the update array

let updateData = [
  { user_key: "1", cuantity: 1},
  { user_key: "1", cuantity: 2},
  { user_key: "2", cuantity: 1},
  { user_key: "2", cuantity: 3}
  ]

FOR e IN updateData
  LET doc = DOCUMENT(CONCAT("test1/",e.user_key))
  UPDATE doc WITH { cuantity: doc.cuantity + e.cuantity }
  IN test1
  LET updated = NEW
RETURN updated

This is the result

[
  {
    "_key": "1", "_id": "test1/1",
    "name": "ivan",
    "cuantity": 2
  },
  {
    "_key": "1", "_id": "test1/1",
    "name": "ivan",
    "cuantity": 3
  },
  {
    "_key": "2", "_id": "test1/2",
    "name": "sergio",
    "cuantity": 2
  },
  {
    "_key": "2", "_id": "test1/2",
    "name": "sergio",
    "cuantity": 4
  }
]

The result of that operation must be that user with "_key": "1" has "cuantity": 4, because in the first iteration it was increased by 1 and in the second iteration by 2. The problem seems to be that ArangoDB cant update the document based in a previous update in the same loop. ¿There is a workaroud oa configuration to achieve this? I am using RocksDB engine.

Arango 3.4 seems to always update the original value when doing updates in a loop. I just ran this on my machine directly in the webGUI :

let myData = [
{ user_key: "1", cuantity: 1},
{ user_key: "1", cuantity: 2},
{ user_key: "2", cuantity: 1},
{ user_key: "2", cuantity: 3},
{ user_key: "3", cuantity: 2}
]

For entry in myData
  LET doc = DOCUMENT(CONCAT("test4/",entry.user_key))
  UPDATE doc WITH { cuantity: doc.cuantity + entry.cuantity }
  IN test4
  LET updated = NEW
RETURN updated

Assuming cuantity for user_key was 1 before the update, I ended up with the incorrect value of 3 instead of 4 by the end of the update.

Having said that, I would think that you may want to aggregate your data before doing the update. For example, if the value for user_key = 1 was updated 100 times in the batch, you probably do not want to run the update 100 times as it could lead to a performance issue. If you pre-aggregate, you could just update the record once at the end. So for example you could do something similar to the following :

let myData = [
{ user_key: "1", cuantity: 1},
{ user_key: "1", cuantity: 2},
{ user_key: "2", cuantity: 1},
{ user_key: "2", cuantity: 3},
{ user_key: "3", cuantity: 2}
]


 LET aggData = ( FOR entry IN myData
  COLLECT theKey = entry.user_key 
  AGGREGATE addedCuantity = sum(entry.cuantity)
  RETURN {theKey, addedCuantity}
  )

  FOR aggEntry IN aggData
  LET doc = DOCUMENT(CONCAT("test4/",aggEntry.theKey))
  UPDATE doc WITH { cuantity: doc.cuantity + aggEntry.addedCuantity }
  IN test4
  LET updated = NEW
  RETURN updated

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM