11__all__ = ["Collection" , "StandardCollection" ]
22
33
4- from typing import Generic , Optional , Tuple , TypeVar
4+ from typing import Generic , Optional , Tuple , TypeVar , cast
55
6- from arangoasync .errno import HTTP_NOT_FOUND , HTTP_PRECONDITION_FAILED
6+ from arangoasync .errno import (
7+ HTTP_BAD_PARAMETER ,
8+ HTTP_NOT_FOUND ,
9+ HTTP_PRECONDITION_FAILED ,
10+ )
711from arangoasync .exceptions import (
812 DocumentGetError ,
13+ DocumentInsertError ,
914 DocumentParseError ,
1015 DocumentRevisionError ,
1116)
1217from arangoasync .executor import ApiExecutor
1318from arangoasync .request import Method , Request
1419from arangoasync .response import Response
1520from arangoasync .serialization import Deserializer , Serializer
16- from arangoasync .typings import Json , Result
21+ from arangoasync .typings import Json , Params , Result
1722
1823T = TypeVar ("T" )
1924U = TypeVar ("U" )
@@ -83,6 +88,21 @@ def _extract_id(self, body: Json) -> str:
8388 except KeyError :
8489 raise DocumentParseError ('Field "_key" or "_id" required' )
8590
91+ def _ensure_key_from_id (self , body : Json ) -> Json :
92+ """Return the body with "_key" field if it has "_id" field.
93+
94+ Args:
95+ body (dict): Document body.
96+
97+ Returns:
98+ dict: Document body with "_key" field if it has "_id" field.
99+ """
100+ if "_id" in body and "_key" not in body :
101+ doc_id = self ._validate_id (body ["_id" ])
102+ body = body .copy ()
103+ body ["_key" ] = doc_id [len (self ._id_prefix ) :]
104+ return body
105+
86106 def _prep_from_doc (
87107 self ,
88108 document : str | Json ,
@@ -172,7 +192,10 @@ async def get(
172192 Raises:
173193 DocumentRevisionError: If the revision is incorrect.
174194 DocumentGetError: If retrieval fails.
175- """
195+
196+ References:
197+ - `get-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#get-a-document>`__
198+ """ # noqa: E501
176199 handle , headers = self ._prep_from_doc (document , rev , check_rev )
177200
178201 if allow_dirty_read :
@@ -195,3 +218,102 @@ def response_handler(resp: Response) -> Optional[U]:
195218 raise DocumentGetError (resp , request )
196219
197220 return await self ._executor .execute (request , response_handler )
221+
222+ async def insert (
223+ self ,
224+ document : T ,
225+ wait_for_sync : Optional [bool ] = None ,
226+ return_new : Optional [bool ] = None ,
227+ return_old : Optional [bool ] = None ,
228+ silent : Optional [bool ] = None ,
229+ overwrite : Optional [bool ] = None ,
230+ overwrite_mode : Optional [str ] = None ,
231+ keep_null : Optional [bool ] = None ,
232+ merge_objects : Optional [bool ] = None ,
233+ refill_index_caches : Optional [bool ] = None ,
234+ version_attribute : Optional [str ] = None ,
235+ ) -> Result [bool | Json ]:
236+ """Insert a new document.
237+
238+ Args:
239+ document (dict): Document to insert. If it contains the "_key" or "_id"
240+ field, the value is used as the key of the new document (otherwise
241+ it is auto-generated). Any "_rev" field is ignored.
242+ wait_for_sync (bool | None): Wait until document has been synced to disk.
243+ return_new (bool | None): Additionally return the complete new document
244+ under the attribute `new` in the result.
245+ return_old (bool | None): Additionally return the complete old document
246+ under the attribute `old` in the result. Only available if the
247+ `overwrite` option is used.
248+ silent (bool | None): If set to `True`, no document metadata is returned.
249+ This can be used to save resources.
250+ overwrite (bool | None): If set to `True`, operation does not fail on
251+ duplicate key and existing document is overwritten (replace-insert).
252+ overwrite_mode (str | None): Overwrite mode. Supersedes **overwrite**
253+ option. May be one of "ignore", "replace", "update" or "conflict".
254+ keep_null (bool | None): If set to `True`, fields with value None are
255+ retained in the document. Otherwise, they are removed completely.
256+ Applies only when **overwrite_mode** is set to "update"
257+ (update-insert).
258+ merge_objects (bool | None): If set to True, sub-dictionaries are merged
259+ instead of the new one overwriting the old one. Applies only when
260+ **overwrite_mode** is set to "update" (update-insert).
261+ refill_index_caches (bool | None): Whether to add new entries to
262+ in-memory index caches if document insertions affect the edge index
263+ or cache-enabled persistent indexes.
264+ version_attribute (str | None): Support for simple external versioning to
265+ document operations. Only applicable if **overwrite** is set to true
266+ or **overwriteMode** is set to "update" or "replace".
267+
268+ References:
269+ - `create-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#create-a-document>`__
270+ """ # noqa: E501
271+ if isinstance (document , dict ):
272+ # We assume that the document deserializer works with dictionaries.
273+ document = cast (T , self ._ensure_key_from_id (document ))
274+
275+ params : Params = {}
276+ if wait_for_sync is not None :
277+ params ["waitForSync" ] = wait_for_sync
278+ if return_new is not None :
279+ params ["returnNew" ] = return_new
280+ if return_old is not None :
281+ params ["returnOld" ] = return_old
282+ if silent is not None :
283+ params ["silent" ] = silent
284+ if overwrite is not None :
285+ params ["overwrite" ] = overwrite
286+ if overwrite_mode is not None :
287+ params ["overwriteMode" ] = overwrite_mode
288+ if keep_null is not None :
289+ params ["keepNull" ] = keep_null
290+ if merge_objects is not None :
291+ params ["mergeObjects" ] = merge_objects
292+ if refill_index_caches is not None :
293+ params ["refillIndexCaches" ] = refill_index_caches
294+ if version_attribute is not None :
295+ params ["versionAttribute" ] = version_attribute
296+
297+ request = Request (
298+ method = Method .POST ,
299+ endpoint = f"/_api/document/{ self ._name } " ,
300+ params = params ,
301+ data = self ._doc_serializer .dumps (document ),
302+ )
303+
304+ def response_handler (resp : Response ) -> bool | Json :
305+ if resp .is_success :
306+ if silent is True :
307+ return True
308+ return self ._executor .deserialize (resp .raw_body )
309+ msg : Optional [str ] = None
310+ if resp .status_code == HTTP_BAD_PARAMETER :
311+ msg = (
312+ "Body does not contain a valid JSON representation of "
313+ "one document."
314+ )
315+ elif resp .status_code == HTTP_NOT_FOUND :
316+ msg = "Collection not found."
317+ raise DocumentInsertError (resp , request , msg )
318+
319+ return await self ._executor .execute (request , response_handler )
0 commit comments