Skip to content

Commit 88efcd4

Browse files
committed
Document manipulation directly from DB class
1 parent 7a5d198 commit 88efcd4

File tree

3 files changed

+399
-4
lines changed

3 files changed

+399
-4
lines changed

arangoasync/collection.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,7 +1653,7 @@ def response_handler(resp: Response) -> bool | Json:
16531653

16541654
async def delete(
16551655
self,
1656-
document: T,
1656+
document: str | T,
16571657
ignore_revs: Optional[bool] = None,
16581658
ignore_missing: bool = False,
16591659
wait_for_sync: Optional[bool] = None,
@@ -1665,7 +1665,7 @@ async def delete(
16651665
"""Delete a document.
16661666
16671667
Args:
1668-
document (dict): Document ID, key or body. The body must contain the
1668+
document (str | dict): Document ID, key or body. The body must contain the
16691669
"_key" or "_id" field.
16701670
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
16711671
document is ignored. If this is set to `False`, then the `_rev`
@@ -1697,6 +1697,8 @@ async def delete(
16971697
References:
16981698
- `remove-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#remove-a-document>`__
16991699
""" # noqa: E501
1700+
handle = self._get_doc_id(cast(str | Json, document))
1701+
17001702
params: Params = {}
17011703
if ignore_revs is not None:
17021704
params["ignoreRevs"] = ignore_revs
@@ -1715,7 +1717,7 @@ async def delete(
17151717

17161718
request = Request(
17171719
method=Method.DELETE,
1718-
endpoint=f"/_api/document/{self._extract_id(cast(Json, document))}",
1720+
endpoint=f"/_api/document/{handle}",
17191721
params=params,
17201722
headers=headers,
17211723
)

arangoasync/database.py

Lines changed: 346 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from warnings import warn
1111

1212
from arangoasync.aql import AQL
13-
from arangoasync.collection import StandardCollection
13+
from arangoasync.collection import Collection, StandardCollection
1414
from arangoasync.connection import Connection
1515
from arangoasync.errno import HTTP_FORBIDDEN, HTTP_NOT_FOUND
1616
from arangoasync.exceptions import (
@@ -684,6 +684,351 @@ def response_handler(resp: Response) -> bool:
684684

685685
return await self._executor.execute(request, response_handler)
686686

687+
async def has_document(
688+
self,
689+
document: str | Json,
690+
allow_dirty_read: bool = False,
691+
if_match: Optional[str] = None,
692+
if_none_match: Optional[str] = None,
693+
) -> Result[bool]:
694+
"""Check if a document exists.
695+
696+
Args:
697+
document (str | dict): Document ID, key or body.
698+
Document body must contain the "_id" field.
699+
allow_dirty_read (bool): Allow reads from followers in a cluster.
700+
if_match (str | None): The document is returned, if it has the same
701+
revision as the given ETag.
702+
if_none_match (str | None): The document is returned, if it has a
703+
different revision than the given ETag.
704+
705+
Returns:
706+
`True` if the document exists, `False` otherwise.
707+
708+
Raises:
709+
DocumentRevisionError: If the revision is incorrect.
710+
DocumentGetError: If retrieval fails.
711+
712+
References:
713+
- `get-a-document-header <https://docs.arangodb.com/stable/develop/http-api/documents/#get-a-document-header>`__
714+
""" # noqa: E501
715+
col = Collection.get_col_name(document)
716+
return await self.collection(col).has(
717+
document,
718+
allow_dirty_read=allow_dirty_read,
719+
if_match=if_match,
720+
if_none_match=if_none_match,
721+
)
722+
723+
async def document(
724+
self,
725+
document: str | Json,
726+
allow_dirty_read: bool = False,
727+
if_match: Optional[str] = None,
728+
if_none_match: Optional[str] = None,
729+
) -> Result[Optional[Json]]:
730+
"""Return a document.
731+
732+
Args:
733+
document (str | dict): Document ID, key or body.
734+
Document body must contain the "_id" field.
735+
allow_dirty_read (bool): Allow reads from followers in a cluster.
736+
if_match (str | None): The document is returned, if it has the same
737+
revision as the given ETag.
738+
if_none_match (str | None): The document is returned, if it has a
739+
different revision than the given ETag.
740+
741+
Returns:
742+
Document or `None` if not found.
743+
744+
Raises:
745+
DocumentRevisionError: If the revision is incorrect.
746+
DocumentGetError: If retrieval fails.
747+
DocumentParseError: If the document is malformed.
748+
749+
References:
750+
- `get-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#get-a-document>`__
751+
""" # noqa: E501
752+
col: StandardCollection[Json, Json, Jsons] = self.collection(
753+
Collection.get_col_name(document)
754+
)
755+
return await col.get(
756+
document,
757+
allow_dirty_read=allow_dirty_read,
758+
if_match=if_match,
759+
if_none_match=if_none_match,
760+
)
761+
762+
async def insert_document(
763+
self,
764+
collection: str,
765+
document: Json,
766+
wait_for_sync: Optional[bool] = None,
767+
return_new: Optional[bool] = None,
768+
return_old: Optional[bool] = None,
769+
silent: Optional[bool] = None,
770+
overwrite: Optional[bool] = None,
771+
overwrite_mode: Optional[str] = None,
772+
keep_null: Optional[bool] = None,
773+
merge_objects: Optional[bool] = None,
774+
refill_index_caches: Optional[bool] = None,
775+
version_attribute: Optional[str] = None,
776+
) -> Result[bool | Json]:
777+
"""Insert a new document.
778+
779+
Args:
780+
collection (str): Collection name.
781+
document (dict): Document to insert. If it contains the "_key" or "_id"
782+
field, the value is used as the key of the new document (otherwise
783+
it is auto-generated). Any "_rev" field is ignored.
784+
wait_for_sync (bool | None): Wait until document has been synced to disk.
785+
return_new (bool | None): Additionally return the complete new document
786+
under the attribute `new` in the result.
787+
return_old (bool | None): Additionally return the complete old document
788+
under the attribute `old` in the result. Only available if the
789+
`overwrite` option is used.
790+
silent (bool | None): If set to `True`, no document metadata is returned.
791+
This can be used to save resources.
792+
overwrite (bool | None): If set to `True`, operation does not fail on
793+
duplicate key and existing document is overwritten (replace-insert).
794+
overwrite_mode (str | None): Overwrite mode. Supersedes **overwrite**
795+
option. May be one of "ignore", "replace", "update" or "conflict".
796+
keep_null (bool | None): If set to `True`, fields with value None are
797+
retained in the document. Otherwise, they are removed completely.
798+
Applies only when **overwrite_mode** is set to "update"
799+
(update-insert).
800+
merge_objects (bool | None): If set to `True`, sub-dictionaries are merged
801+
instead of the new one overwriting the old one. Applies only when
802+
**overwrite_mode** is set to "update" (update-insert).
803+
refill_index_caches (bool | None): Whether to add new entries to
804+
in-memory index caches if document insertions affect the edge index
805+
or cache-enabled persistent indexes.
806+
version_attribute (str | None): Support for simple external versioning to
807+
document operations. Only applicable if **overwrite** is set to `True`
808+
or **overwrite_mode** is set to "update" or "replace".
809+
810+
Returns:
811+
bool | dict: Document metadata (e.g. document id, key, revision) or `True`
812+
if **silent** is set to `True`.
813+
814+
Raises:
815+
DocumentInsertError: If insertion fails.
816+
DocumentParseError: If the document is malformed.
817+
818+
References:
819+
- `create-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#create-a-document>`__
820+
""" # noqa: E501
821+
col: StandardCollection[Json, Json, Jsons] = self.collection(collection)
822+
return await col.insert(
823+
document,
824+
wait_for_sync=wait_for_sync,
825+
return_new=return_new,
826+
return_old=return_old,
827+
silent=silent,
828+
overwrite=overwrite,
829+
overwrite_mode=overwrite_mode,
830+
keep_null=keep_null,
831+
merge_objects=merge_objects,
832+
refill_index_caches=refill_index_caches,
833+
version_attribute=version_attribute,
834+
)
835+
836+
async def update_document(
837+
self,
838+
collection: str,
839+
document: Json,
840+
ignore_revs: Optional[bool] = None,
841+
wait_for_sync: Optional[bool] = None,
842+
return_new: Optional[bool] = None,
843+
return_old: Optional[bool] = None,
844+
silent: Optional[bool] = None,
845+
keep_null: Optional[bool] = None,
846+
merge_objects: Optional[bool] = None,
847+
refill_index_caches: Optional[bool] = None,
848+
version_attribute: Optional[str] = None,
849+
if_match: Optional[str] = None,
850+
) -> Result[bool | Json]:
851+
"""Update a document.
852+
853+
Args:
854+
collection (str): Collection name.
855+
document (dict): Partial or full document with the updated values.
856+
It must contain the "_key" or "_id" field.
857+
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
858+
document is ignored. If this is set to `False`, then the `_rev`
859+
attribute given in the body document is taken as a precondition.
860+
The document is only updated if the current revision is the one
861+
specified.
862+
wait_for_sync (bool | None): Wait until document has been synced to disk.
863+
return_new (bool | None): Additionally return the complete new document
864+
under the attribute `new` in the result.
865+
return_old (bool | None): Additionally return the complete old document
866+
under the attribute `old` in the result.
867+
silent (bool | None): If set to `True`, no document metadata is returned.
868+
This can be used to save resources.
869+
keep_null (bool | None): If the intention is to delete existing attributes
870+
with the patch command, set this parameter to `False`.
871+
merge_objects (bool | None): Controls whether objects (not arrays) are
872+
merged if present in both the existing and the patch document.
873+
If set to `False`, the value in the patch document overwrites the
874+
existing document’s value. If set to `True`, objects are merged.
875+
refill_index_caches (bool | None): Whether to add new entries to
876+
in-memory index caches if document updates affect the edge index
877+
or cache-enabled persistent indexes.
878+
version_attribute (str | None): Support for simple external versioning to
879+
document operations.
880+
if_match (str | None): You can conditionally update a document based on a
881+
target revision id by using the "if-match" HTTP header.
882+
883+
Returns:
884+
bool | dict: Document metadata (e.g. document id, key, revision) or `True`
885+
if **silent** is set to `True`.
886+
887+
Raises:
888+
DocumentRevisionError: If precondition was violated.
889+
DocumentUpdateError: If update fails.
890+
891+
References:
892+
- `update-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#update-a-document>`__
893+
""" # noqa: E501
894+
col: StandardCollection[Json, Json, Jsons] = self.collection(collection)
895+
return await col.update(
896+
document,
897+
ignore_revs=ignore_revs,
898+
wait_for_sync=wait_for_sync,
899+
return_new=return_new,
900+
return_old=return_old,
901+
silent=silent,
902+
keep_null=keep_null,
903+
merge_objects=merge_objects,
904+
refill_index_caches=refill_index_caches,
905+
version_attribute=version_attribute,
906+
if_match=if_match,
907+
)
908+
909+
async def replace_document(
910+
self,
911+
collection: str,
912+
document: Json,
913+
ignore_revs: Optional[bool] = None,
914+
wait_for_sync: Optional[bool] = None,
915+
return_new: Optional[bool] = None,
916+
return_old: Optional[bool] = None,
917+
silent: Optional[bool] = None,
918+
refill_index_caches: Optional[bool] = None,
919+
version_attribute: Optional[str] = None,
920+
if_match: Optional[str] = None,
921+
) -> Result[bool | Json]:
922+
"""Replace a document.
923+
924+
Args:
925+
collection (str): Collection name.
926+
document (dict): New document. It must contain the "_key" or "_id" field.
927+
Edge document must also have "_from" and "_to" fields.
928+
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
929+
document is ignored. If this is set to `False`, then the `_rev`
930+
attribute given in the body document is taken as a precondition.
931+
The document is only replaced if the current revision is the one
932+
specified.
933+
wait_for_sync (bool | None): Wait until document has been synced to disk.
934+
return_new (bool | None): Additionally return the complete new document
935+
under the attribute `new` in the result.
936+
return_old (bool | None): Additionally return the complete old document
937+
under the attribute `old` in the result.
938+
silent (bool | None): If set to `True`, no document metadata is returned.
939+
This can be used to save resources.
940+
refill_index_caches (bool | None): Whether to add new entries to
941+
in-memory index caches if document updates affect the edge index
942+
or cache-enabled persistent indexes.
943+
version_attribute (str | None): Support for simple external versioning to
944+
document operations.
945+
if_match (str | None): You can conditionally replace a document based on a
946+
target revision id by using the "if-match" HTTP header.
947+
948+
Returns:
949+
bool | dict: Document metadata (e.g. document id, key, revision) or `True`
950+
if **silent** is set to `True`.
951+
952+
Raises:
953+
DocumentRevisionError: If precondition was violated.
954+
DocumentReplaceError: If replace fails.
955+
956+
References:
957+
- `replace-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#replace-a-document>`__
958+
""" # noqa: E501
959+
col: StandardCollection[Json, Json, Jsons] = self.collection(collection)
960+
return await col.replace(
961+
document,
962+
ignore_revs=ignore_revs,
963+
wait_for_sync=wait_for_sync,
964+
return_new=return_new,
965+
return_old=return_old,
966+
silent=silent,
967+
refill_index_caches=refill_index_caches,
968+
version_attribute=version_attribute,
969+
if_match=if_match,
970+
)
971+
972+
async def delete_document(
973+
self,
974+
collection: str,
975+
document: str | Json,
976+
ignore_revs: Optional[bool] = None,
977+
ignore_missing: bool = False,
978+
wait_for_sync: Optional[bool] = None,
979+
return_old: Optional[bool] = None,
980+
silent: Optional[bool] = None,
981+
refill_index_caches: Optional[bool] = None,
982+
if_match: Optional[str] = None,
983+
) -> Result[bool | Json]:
984+
"""Delete a document.
985+
986+
Args:
987+
collection (str): Collection name.
988+
document (str | dict): Document ID, key or body. The body must contain the
989+
"_key" or "_id" field.
990+
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
991+
document is ignored. If this is set to `False`, then the `_rev`
992+
attribute given in the body document is taken as a precondition.
993+
The document is only replaced if the current revision is the one
994+
specified.
995+
ignore_missing (bool): Do not raise an exception on missing document.
996+
This parameter has no effect in transactions where an exception is
997+
always raised on failures.
998+
wait_for_sync (bool | None): Wait until operation has been synced to disk.
999+
return_old (bool | None): Additionally return the complete old document
1000+
under the attribute `old` in the result.
1001+
silent (bool | None): If set to `True`, no document metadata is returned.
1002+
This can be used to save resources.
1003+
refill_index_caches (bool | None): Whether to add new entries to
1004+
in-memory index caches if document updates affect the edge index
1005+
or cache-enabled persistent indexes.
1006+
if_match (bool | None): You can conditionally remove a document based
1007+
on a target revision id by using the "if-match" HTTP header.
1008+
1009+
Returns:
1010+
bool | dict: Document metadata (e.g. document id, key, revision) or `True`
1011+
if **silent** is set to `True` and the document was found.
1012+
1013+
Raises:
1014+
DocumentRevisionError: If precondition was violated.
1015+
DocumentDeleteError: If deletion fails.
1016+
1017+
References:
1018+
- `remove-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#remove-a-document>`__
1019+
""" # noqa: E501
1020+
col: StandardCollection[Json, Json, Jsons] = self.collection(collection)
1021+
return await col.delete(
1022+
document,
1023+
ignore_revs=ignore_revs,
1024+
ignore_missing=ignore_missing,
1025+
wait_for_sync=wait_for_sync,
1026+
return_old=return_old,
1027+
silent=silent,
1028+
refill_index_caches=refill_index_caches,
1029+
if_match=if_match,
1030+
)
1031+
6871032
def graph(
6881033
self,
6891034
name: str,

0 commit comments

Comments
 (0)