Skip to content

Commit c5bf9af

Browse files
committed
Adding update_many method
1 parent e75b469 commit c5bf9af

File tree

2 files changed

+139
-7
lines changed

2 files changed

+139
-7
lines changed

arangoasync/collection.py

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,9 +1288,8 @@ async def replace_many(
12881288
(returns exception object).
12891289
12901290
Args:
1291-
documents (list): New documents to replace the old ones. If an item
1292-
contains the "_key" or "_id" field, the value is used as the key
1293-
of the new document (otherwise it is auto-generated).
1291+
documents (list): New documents to replace the old ones. An item must
1292+
contain the "_key" or "_id" field.
12941293
wait_for_sync (bool | None): Wait until documents have been synced to disk.
12951294
ignore_revs (bool | None): If this is set to `False`, then any `_rev`
12961295
attribute given in a body document is taken as a precondition. The
@@ -1299,8 +1298,7 @@ async def replace_many(
12991298
return_new (bool | None): Additionally return the complete new document
13001299
under the attribute `new` in the result.
13011300
return_old (bool | None): Additionally return the complete old document
1302-
under the attribute `old` in the result. Only available if the
1303-
`overwrite` option is used.
1301+
under the attribute `old` in the result.
13041302
silent (bool | None): If set to `True`, an empty object is returned as
13051303
response if all document operations succeed. No meta-data is returned
13061304
for the created documents. If any of the operations raises an error,
@@ -1309,8 +1307,7 @@ async def replace_many(
13091307
in-memory index caches if document operations affect the edge index
13101308
or cache-enabled persistent indexes.
13111309
version_attribute (str | None): Support for simple external versioning to
1312-
document operations. Only applicable if **overwrite** is set to `True`
1313-
or **overwrite_mode** is set to "update" or "replace".
1310+
document operations.
13141311
13151312
Returns:
13161313
list: Documents metadata (e.g. document id, key, revision) and
@@ -1353,3 +1350,100 @@ def response_handler(
13531350
return self.deserializer.loads_many(resp.raw_body)
13541351

13551352
return await self._executor.execute(request, response_handler)
1353+
1354+
async def update_many(
1355+
self,
1356+
documents: Sequence[T],
1357+
wait_for_sync: Optional[bool] = None,
1358+
ignore_revs: Optional[bool] = None,
1359+
return_new: Optional[bool] = None,
1360+
return_old: Optional[bool] = None,
1361+
silent: Optional[bool] = None,
1362+
keep_null: Optional[bool] = None,
1363+
merge_objects: Optional[bool] = None,
1364+
refill_index_caches: Optional[bool] = None,
1365+
version_attribute: Optional[str] = None,
1366+
) -> Result[Jsons]:
1367+
"""Insert multiple documents.
1368+
1369+
Note:
1370+
If updating a document fails, the exception is not raised but
1371+
returned as an object in the "errors" list. It is up to you to
1372+
inspect the list to determine which documents were updated
1373+
successfully (returned as document metadata) and which were not
1374+
(returned as exception object).
1375+
1376+
Args:
1377+
documents (list): Documents to update. An item must contain the "_key" or
1378+
"_id" field.
1379+
wait_for_sync (bool | None): Wait until documents have been synced to disk.
1380+
ignore_revs (bool | None): If this is set to `False`, then any `_rev`
1381+
attribute given in a body document is taken as a precondition. The
1382+
document is only updated if the current revision is the one
1383+
specified.
1384+
return_new (bool | None): Additionally return the complete new document
1385+
under the attribute `new` in the result.
1386+
return_old (bool | None): Additionally return the complete old document
1387+
under the attribute `old` in the result.
1388+
silent (bool | None): If set to `True`, an empty object is returned as
1389+
response if all document operations succeed. No meta-data is returned
1390+
for the created documents. If any of the operations raises an error,
1391+
an array with the error object(s) is returned.
1392+
keep_null (bool | None): If set to `True`, fields with value None are
1393+
retained in the document. Otherwise, they are removed completely.
1394+
Applies only when **overwrite_mode** is set to "update"
1395+
(update-insert).
1396+
merge_objects (bool | None): If set to `True`, sub-dictionaries are merged
1397+
instead of the new one overwriting the old one. Applies only when
1398+
**overwrite_mode** is set to "update" (update-insert).
1399+
refill_index_caches (bool | None): Whether to add new entries to
1400+
in-memory index caches if document operations affect the edge index
1401+
or cache-enabled persistent indexes.
1402+
version_attribute (str | None): Support for simple external versioning to
1403+
document operations.
1404+
1405+
Returns:
1406+
list: Documents metadata (e.g. document id, key, revision) and
1407+
errors or just errors if **silent** is set to `True`.
1408+
1409+
Raises:
1410+
DocumentUpdateError: If update fails.
1411+
1412+
References:
1413+
- `update-multiple-documents <https://docs.arangodb.com/stable/develop/http-api/documents/#update-multiple-documents>`__
1414+
""" # noqa: E501
1415+
params: Params = {}
1416+
if wait_for_sync is not None:
1417+
params["waitForSync"] = wait_for_sync
1418+
if ignore_revs is not None:
1419+
params["ignoreRevs"] = ignore_revs
1420+
if return_new is not None:
1421+
params["returnNew"] = return_new
1422+
if return_old is not None:
1423+
params["returnOld"] = return_old
1424+
if silent is not None:
1425+
params["silent"] = silent
1426+
if keep_null is not None:
1427+
params["keepNull"] = keep_null
1428+
if merge_objects is not None:
1429+
params["mergeObjects"] = merge_objects
1430+
if refill_index_caches is not None:
1431+
params["refillIndexCaches"] = refill_index_caches
1432+
if version_attribute is not None:
1433+
params["versionAttribute"] = version_attribute
1434+
1435+
request = Request(
1436+
method=Method.PATCH,
1437+
endpoint=f"/_api/document/{self.name}",
1438+
data=self._doc_serializer.dumps(documents),
1439+
params=params,
1440+
)
1441+
1442+
def response_handler(
1443+
resp: Response,
1444+
) -> Jsons:
1445+
if not resp.is_success:
1446+
raise DocumentUpdateError(resp, request)
1447+
return self.deserializer.loads_many(resp.raw_body)
1448+
1449+
return await self._executor.execute(request, response_handler)

tests/test_document.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ async def test_document_replace_many(doc_col, bad_col, docs):
362362
assert len(result) == len(docs)
363363
for doc in result:
364364
assert doc["new"]["val"] == 42
365+
assert "text" not in doc["new"]
365366

366367
# Silent mode
367368
result = await doc_col.replace_many(docs, silent=True)
@@ -371,3 +372,40 @@ async def test_document_replace_many(doc_col, bad_col, docs):
371372
assert len(result) == len(docs)
372373
for res in result:
373374
assert "error" in res
375+
376+
377+
@pytest.mark.asyncio
378+
async def test_document_update_many(doc_col, bad_col, docs):
379+
# Check errors
380+
with pytest.raises(DocumentUpdateError):
381+
await bad_col.update_many(docs)
382+
383+
# Empty list
384+
result = await doc_col.update_many([])
385+
assert len(result) == 0
386+
387+
# Update "not found" documents
388+
result = await doc_col.update_many(docs, return_new=True)
389+
assert len(result) == len(docs)
390+
for res in result:
391+
assert "error" in res
392+
393+
# Update successfully
394+
result = await doc_col.insert_many(docs, return_new=True)
395+
updates = []
396+
for doc in result:
397+
updates.append({"_key": doc["_key"], "val": 42})
398+
result = await doc_col.update_many(updates, return_new=True)
399+
assert len(result) == len(docs)
400+
for doc in result:
401+
assert doc["new"]["val"] == 42
402+
assert "text" in doc["new"]
403+
404+
# Silent mode
405+
result = await doc_col.update_many(docs, silent=True)
406+
assert len(result) == 0
407+
await doc_col.truncate()
408+
result = await doc_col.update_many(docs, silent=True)
409+
assert len(result) == len(docs)
410+
for res in result:
411+
assert "error" in res

0 commit comments

Comments
 (0)