1
1
__all__ = ["Collection" , "StandardCollection" ]
2
2
3
3
4
- from typing import Generic , Optional , Tuple , TypeVar
4
+ from typing import Generic , Optional , Tuple , TypeVar , cast
5
5
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
+ )
7
11
from arangoasync .exceptions import (
8
12
DocumentGetError ,
13
+ DocumentInsertError ,
9
14
DocumentParseError ,
10
15
DocumentRevisionError ,
11
16
)
12
17
from arangoasync .executor import ApiExecutor
13
18
from arangoasync .request import Method , Request
14
19
from arangoasync .response import Response
15
20
from arangoasync .serialization import Deserializer , Serializer
16
- from arangoasync .typings import Json , Result
21
+ from arangoasync .typings import Json , Params , Result
17
22
18
23
T = TypeVar ("T" )
19
24
U = TypeVar ("U" )
@@ -83,6 +88,21 @@ def _extract_id(self, body: Json) -> str:
83
88
except KeyError :
84
89
raise DocumentParseError ('Field "_key" or "_id" required' )
85
90
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
+
86
106
def _prep_from_doc (
87
107
self ,
88
108
document : str | Json ,
@@ -172,7 +192,10 @@ async def get(
172
192
Raises:
173
193
DocumentRevisionError: If the revision is incorrect.
174
194
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
176
199
handle , headers = self ._prep_from_doc (document , rev , check_rev )
177
200
178
201
if allow_dirty_read :
@@ -195,3 +218,102 @@ def response_handler(resp: Response) -> Optional[U]:
195
218
raise DocumentGetError (resp , request )
196
219
197
220
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