Skip to content

Commit 83054a3

Browse files
authored
More on document manipulation (#54)
* Document manipulation directly from DB class * Removing collection parameter * Updating docs
1 parent 7a5d198 commit 83054a3

File tree

4 files changed

+449
-4
lines changed

4 files changed

+449
-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+
document: Json,
839+
ignore_revs: Optional[bool] = None,
840+
wait_for_sync: Optional[bool] = None,
841+
return_new: Optional[bool] = None,
842+
return_old: Optional[bool] = None,
843+
silent: Optional[bool] = None,
844+
keep_null: Optional[bool] = None,
845+
merge_objects: Optional[bool] = None,
846+
refill_index_caches: Optional[bool] = None,
847+
version_attribute: Optional[str] = None,
848+
if_match: Optional[str] = None,
849+
) -> Result[bool | Json]:
850+
"""Update a document.
851+
852+
Args:
853+
document (dict): Partial or full document with the updated values.
854+
It must contain the "_key" or "_id" field.
855+
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
856+
document is ignored. If this is set to `False`, then the `_rev`
857+
attribute given in the body document is taken as a precondition.
858+
The document is only updated if the current revision is the one
859+
specified.
860+
wait_for_sync (bool | None): Wait until document has been synced to disk.
861+
return_new (bool | None): Additionally return the complete new document
862+
under the attribute `new` in the result.
863+
return_old (bool | None): Additionally return the complete old document
864+
under the attribute `old` in the result.
865+
silent (bool | None): If set to `True`, no document metadata is returned.
866+
This can be used to save resources.
867+
keep_null (bool | None): If the intention is to delete existing attributes
868+
with the patch command, set this parameter to `False`.
869+
merge_objects (bool | None): Controls whether objects (not arrays) are
870+
merged if present in both the existing and the patch document.
871+
If set to `False`, the value in the patch document overwrites the
872+
existing document’s value. If set to `True`, objects are merged.
873+
refill_index_caches (bool | None): Whether to add new entries to
874+
in-memory index caches if document updates affect the edge index
875+
or cache-enabled persistent indexes.
876+
version_attribute (str | None): Support for simple external versioning to
877+
document operations.
878+
if_match (str | None): You can conditionally update a document based on a
879+
target revision id by using the "if-match" HTTP header.
880+
881+
Returns:
882+
bool | dict: Document metadata (e.g. document id, key, revision) or `True`
883+
if **silent** is set to `True`.
884+
885+
Raises:
886+
DocumentRevisionError: If precondition was violated.
887+
DocumentUpdateError: If update fails.
888+
889+
References:
890+
- `update-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#update-a-document>`__
891+
""" # noqa: E501
892+
col: StandardCollection[Json, Json, Jsons] = self.collection(
893+
Collection.get_col_name(document)
894+
)
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+
document: Json,
912+
ignore_revs: Optional[bool] = None,
913+
wait_for_sync: Optional[bool] = None,
914+
return_new: Optional[bool] = None,
915+
return_old: Optional[bool] = None,
916+
silent: Optional[bool] = None,
917+
refill_index_caches: Optional[bool] = None,
918+
version_attribute: Optional[str] = None,
919+
if_match: Optional[str] = None,
920+
) -> Result[bool | Json]:
921+
"""Replace a document.
922+
923+
Args:
924+
document (dict): New document. It must contain the "_key" or "_id" field.
925+
Edge document must also have "_from" and "_to" fields.
926+
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
927+
document is ignored. If this is set to `False`, then the `_rev`
928+
attribute given in the body document is taken as a precondition.
929+
The document is only replaced if the current revision is the one
930+
specified.
931+
wait_for_sync (bool | None): Wait until document has been synced to disk.
932+
return_new (bool | None): Additionally return the complete new document
933+
under the attribute `new` in the result.
934+
return_old (bool | None): Additionally return the complete old document
935+
under the attribute `old` in the result.
936+
silent (bool | None): If set to `True`, no document metadata is returned.
937+
This can be used to save resources.
938+
refill_index_caches (bool | None): Whether to add new entries to
939+
in-memory index caches if document updates affect the edge index
940+
or cache-enabled persistent indexes.
941+
version_attribute (str | None): Support for simple external versioning to
942+
document operations.
943+
if_match (str | None): You can conditionally replace a document based on a
944+
target revision id by using the "if-match" HTTP header.
945+
946+
Returns:
947+
bool | dict: Document metadata (e.g. document id, key, revision) or `True`
948+
if **silent** is set to `True`.
949+
950+
Raises:
951+
DocumentRevisionError: If precondition was violated.
952+
DocumentReplaceError: If replace fails.
953+
954+
References:
955+
- `replace-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#replace-a-document>`__
956+
""" # noqa: E501
957+
col: StandardCollection[Json, Json, Jsons] = self.collection(
958+
Collection.get_col_name(document)
959+
)
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+
document: str | Json,
975+
ignore_revs: Optional[bool] = None,
976+
ignore_missing: bool = False,
977+
wait_for_sync: Optional[bool] = None,
978+
return_old: Optional[bool] = None,
979+
silent: Optional[bool] = None,
980+
refill_index_caches: Optional[bool] = None,
981+
if_match: Optional[str] = None,
982+
) -> Result[bool | Json]:
983+
"""Delete a document.
984+
985+
Args:
986+
document (str | dict): Document ID, key or body. The body must contain the
987+
"_key" or "_id" field.
988+
ignore_revs (bool | None): If set to `True`, the `_rev` attribute in the
989+
document is ignored. If this is set to `False`, then the `_rev`
990+
attribute given in the body document is taken as a precondition.
991+
The document is only replaced if the current revision is the one
992+
specified.
993+
ignore_missing (bool): Do not raise an exception on missing document.
994+
This parameter has no effect in transactions where an exception is
995+
always raised on failures.
996+
wait_for_sync (bool | None): Wait until operation has been synced to disk.
997+
return_old (bool | None): Additionally return the complete old document
998+
under the attribute `old` in the result.
999+
silent (bool | None): If set to `True`, no document metadata is returned.
1000+
This can be used to save resources.
1001+
refill_index_caches (bool | None): Whether to add new entries to
1002+
in-memory index caches if document updates affect the edge index
1003+
or cache-enabled persistent indexes.
1004+
if_match (bool | None): You can conditionally remove a document based
1005+
on a target revision id by using the "if-match" HTTP header.
1006+
1007+
Returns:
1008+
bool | dict: Document metadata (e.g. document id, key, revision) or `True`
1009+
if **silent** is set to `True` and the document was found.
1010+
1011+
Raises:
1012+
DocumentRevisionError: If precondition was violated.
1013+
DocumentDeleteError: If deletion fails.
1014+
1015+
References:
1016+
- `remove-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#remove-a-document>`__
1017+
""" # noqa: E501
1018+
col: StandardCollection[Json, Json, Jsons] = self.collection(
1019+
Collection.get_col_name(document)
1020+
)
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)