Skip to content

Commit afacf87

Browse files
committed
Adding get_many method
1 parent 6e3e364 commit afacf87

File tree

3 files changed

+89
-3
lines changed

3 files changed

+89
-3
lines changed

arangoasync/collection.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
__all__ = ["Collection", "StandardCollection"]
22

33

4-
from typing import Generic, List, Optional, Tuple, TypeVar, cast
4+
from typing import Generic, List, Optional, Sequence, Tuple, TypeVar, cast
55

66
from arangoasync.errno import (
77
DOCUMENT_NOT_FOUND,
@@ -889,3 +889,55 @@ def response_handler(resp: Response) -> bool | Json:
889889
raise DocumentDeleteError(resp, request, msg)
890890

891891
return await self._executor.execute(request, response_handler)
892+
893+
async def get_many(
894+
self,
895+
documents: Sequence[str | Json],
896+
allow_dirty_read: Optional[bool] = None,
897+
ignore_revs: Optional[bool] = None,
898+
) -> Result[V]:
899+
"""Return multiple documents ignoring any missing ones.
900+
901+
Args:
902+
documents (list): List of document IDs, keys or bodies. A search document
903+
must contain at least a value for the `_key` field. A value for `_rev`
904+
may be specified to verify whether the document has the same revision
905+
value, unless `ignoreRevs` is set to false.
906+
allow_dirty_read (bool | None): Allow reads from followers in a cluster.
907+
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
908+
document is ignored. If this is set to `False`, then the `_rev`
909+
attribute given in the body document is taken as a precondition.
910+
The document is only replaced if the current revision is the one
911+
specified.
912+
913+
Returns:
914+
list: List of documents. Missing ones are not included.
915+
916+
Raises:
917+
DocumentGetError: If retrieval fails.
918+
919+
References:
920+
- `get-multiple-documents <https://docs.arangodb.com/stable/develop/http-api/documents/#get-multiple-documents>`__
921+
""" # noqa: E501
922+
params: Params = {"onlyget": True}
923+
if ignore_revs is not None:
924+
params["ignoreRevs"] = ignore_revs
925+
926+
headers: RequestHeaders = {}
927+
if allow_dirty_read is not None:
928+
headers["x-arango-allow-dirty-read"] = allow_dirty_read
929+
930+
request = Request(
931+
method=Method.PUT,
932+
endpoint=f"/_api/document/{self.name}",
933+
params=params,
934+
headers=headers,
935+
data=self.serializer.dumps(documents),
936+
)
937+
938+
def response_handler(resp: Response) -> V:
939+
if not resp.is_success:
940+
raise DocumentGetError(resp, request)
941+
return self._doc_deserializer.loads_many(resp.raw_body)
942+
943+
return await self._executor.execute(request, response_handler)

arangoasync/serialization.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import json
1111
from abc import ABC, abstractmethod
12-
from typing import Generic, TypeVar
12+
from typing import Generic, Sequence, TypeVar
1313

1414
from arangoasync.exceptions import DeserializationError, SerializationError
1515
from arangoasync.typings import Json, Jsons
@@ -26,7 +26,7 @@ class Serializer(ABC, Generic[T]): # pragma: no cover
2626
"""
2727

2828
@abstractmethod
29-
def dumps(self, data: T) -> str:
29+
def dumps(self, data: str | bool | T | Sequence[T | str]) -> str:
3030
"""Serialize any generic data.
3131
3232
Args:

tests/test_document.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import asyncio
2+
13
import pytest
24

35
from arangoasync.exceptions import (
@@ -200,3 +202,35 @@ async def test_document_has(doc_col, bad_col, docs):
200202
await doc_col.has(inserted["_id"], if_none_match=inserted["_rev"])
201203
with pytest.raises(DocumentRevisionError):
202204
await doc_col.has(inserted["_id"], if_match="foobar")
205+
206+
207+
@pytest.mark.asyncio
208+
async def test_document_get_many(doc_col, bad_col, docs):
209+
# Test with invalid collection
210+
with pytest.raises(DocumentGetError):
211+
await bad_col.get_many(["non-existent"])
212+
213+
# Insert all documents first
214+
await asyncio.gather(*[doc_col.insert(doc) for doc in docs])
215+
216+
# Test with good keys
217+
many = await doc_col.get_many([doc["_key"] for doc in docs])
218+
assert len(many) == len(docs)
219+
220+
# Test with full documents
221+
many = await doc_col.get_many(docs)
222+
assert len(many) == len(docs)
223+
224+
# Revs
225+
bad_rev = many
226+
bad_rev[0]["_rev"] = "foobar"
227+
many = await doc_col.get_many([bad_rev[0]], ignore_revs=True)
228+
assert len(many) == 1
229+
assert "error" not in many[0]
230+
many = await doc_col.get_many([bad_rev[0]], ignore_revs=False)
231+
assert len(many) == 1
232+
assert "error" in many[0]
233+
234+
# Empty list
235+
many = await doc_col.get_many([])
236+
assert len(many) == 0

0 commit comments

Comments
 (0)