Skip to content

Commit e75b469

Browse files
committed
Adding update_many method
1 parent 00dfa61 commit e75b469

File tree

2 files changed

+127
-4
lines changed

2 files changed

+127
-4
lines changed

arangoasync/collection.py

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,7 +1177,7 @@ async def insert_many(
11771177
merge_objects: Optional[bool] = None,
11781178
refill_index_caches: Optional[bool] = None,
11791179
version_attribute: Optional[str] = None,
1180-
) -> Result[Optional[Jsons]]:
1180+
) -> Result[Jsons]:
11811181
"""Insert multiple documents.
11821182
11831183
Note:
@@ -1213,15 +1213,15 @@ async def insert_many(
12131213
instead of the new one overwriting the old one. Applies only when
12141214
**overwrite_mode** is set to "update" (update-insert).
12151215
refill_index_caches (bool | None): Whether to add new entries to
1216-
in-memory index caches if document insertions affect the edge index
1216+
in-memory index caches if document operations affect the edge index
12171217
or cache-enabled persistent indexes.
12181218
version_attribute (str | None): Support for simple external versioning to
12191219
document operations. Only applicable if **overwrite** is set to `True`
12201220
or **overwrite_mode** is set to "update" or "replace".
12211221
12221222
Returns:
1223-
None | list: Documents metadata (e.g. document id, key, revision) and
1224-
errors or `None` if **silent** is set to `True`.
1223+
list: Documents metadata (e.g. document id, key, revision) and
1224+
errors or just errors if **silent** is set to `True`.
12251225
12261226
Raises:
12271227
DocumentInsertError: If insertion fails.
@@ -1266,3 +1266,90 @@ def response_handler(
12661266
return self.deserializer.loads_many(resp.raw_body)
12671267

12681268
return await self._executor.execute(request, response_handler)
1269+
1270+
async def replace_many(
1271+
self,
1272+
documents: Sequence[T],
1273+
wait_for_sync: Optional[bool] = None,
1274+
ignore_revs: Optional[bool] = None,
1275+
return_new: Optional[bool] = None,
1276+
return_old: Optional[bool] = None,
1277+
silent: Optional[bool] = None,
1278+
refill_index_caches: Optional[bool] = None,
1279+
version_attribute: Optional[str] = None,
1280+
) -> Result[Jsons]:
1281+
"""Insert multiple documents.
1282+
1283+
Note:
1284+
If replacing a document fails, the exception is not raised but
1285+
returned as an object in the "errors" list. It is up to you to
1286+
inspect the list to determine which documents were replaced
1287+
successfully (returns document metadata) and which were not
1288+
(returns exception object).
1289+
1290+
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).
1294+
wait_for_sync (bool | None): Wait until documents have been synced to disk.
1295+
ignore_revs (bool | None): If this is set to `False`, then any `_rev`
1296+
attribute given in a body document is taken as a precondition. The
1297+
document is only replaced if the current revision is the one
1298+
specified.
1299+
return_new (bool | None): Additionally return the complete new document
1300+
under the attribute `new` in the result.
1301+
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.
1304+
silent (bool | None): If set to `True`, an empty object is returned as
1305+
response if all document operations succeed. No meta-data is returned
1306+
for the created documents. If any of the operations raises an error,
1307+
an array with the error object(s) is returned.
1308+
refill_index_caches (bool | None): Whether to add new entries to
1309+
in-memory index caches if document operations affect the edge index
1310+
or cache-enabled persistent indexes.
1311+
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".
1314+
1315+
Returns:
1316+
list: Documents metadata (e.g. document id, key, revision) and
1317+
errors or just errors if **silent** is set to `True`.
1318+
1319+
Raises:
1320+
DocumentReplaceError: If replacing fails.
1321+
1322+
References:
1323+
- `replace-multiple-documents <https://docs.arangodb.com/stable/develop/http-api/documents/#replace-multiple-documents>`__
1324+
""" # noqa: E501
1325+
params: Params = {}
1326+
if wait_for_sync is not None:
1327+
params["waitForSync"] = wait_for_sync
1328+
if ignore_revs is not None:
1329+
params["ignoreRevs"] = ignore_revs
1330+
if return_new is not None:
1331+
params["returnNew"] = return_new
1332+
if return_old is not None:
1333+
params["returnOld"] = return_old
1334+
if silent is not None:
1335+
params["silent"] = silent
1336+
if refill_index_caches is not None:
1337+
params["refillIndexCaches"] = refill_index_caches
1338+
if version_attribute is not None:
1339+
params["versionAttribute"] = version_attribute
1340+
1341+
request = Request(
1342+
method=Method.PUT,
1343+
endpoint=f"/_api/document/{self.name}",
1344+
data=self._doc_serializer.dumps(documents),
1345+
params=params,
1346+
)
1347+
1348+
def response_handler(
1349+
resp: Response,
1350+
) -> Jsons:
1351+
if not resp.is_success:
1352+
raise DocumentReplaceError(resp, request)
1353+
return self.deserializer.loads_many(resp.raw_body)
1354+
1355+
return await self._executor.execute(request, response_handler)

tests/test_document.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,3 +335,39 @@ async def test_document_insert_many(doc_col, bad_col, docs):
335335
await doc_col.truncate()
336336
result = await doc_col.insert_many(docs, silent=True)
337337
assert len(result) == 0
338+
339+
340+
@pytest.mark.asyncio
341+
async def test_document_replace_many(doc_col, bad_col, docs):
342+
# Check errors
343+
with pytest.raises(DocumentReplaceError):
344+
await bad_col.replace_many(docs)
345+
346+
# Empty list
347+
result = await doc_col.replace_many([])
348+
assert len(result) == 0
349+
350+
# Replace "not found" documents
351+
result = await doc_col.replace_many(docs, return_new=True)
352+
assert len(result) == len(docs)
353+
for res in result:
354+
assert "error" in res
355+
356+
# Replace successfully
357+
result = await doc_col.insert_many(docs, return_new=True)
358+
replacements = []
359+
for doc in result:
360+
replacements.append({"_key": doc["_key"], "val": 42})
361+
result = await doc_col.replace_many(replacements, return_new=True)
362+
assert len(result) == len(docs)
363+
for doc in result:
364+
assert doc["new"]["val"] == 42
365+
366+
# Silent mode
367+
result = await doc_col.replace_many(docs, silent=True)
368+
assert len(result) == 0
369+
await doc_col.truncate()
370+
result = await doc_col.replace_many(docs, silent=True)
371+
assert len(result) == len(docs)
372+
for res in result:
373+
assert "error" in res

0 commit comments

Comments
 (0)