1__all__ = ["Graph"]
2
3from typing import List, Optional, Sequence, Union
4
5from arango.api import ApiGroup
6from arango.collection import EdgeCollection, VertexCollection
7from arango.connection import Connection
8from arango.exceptions import (
9    EdgeDefinitionCreateError,
10    EdgeDefinitionDeleteError,
11    EdgeDefinitionListError,
12    EdgeDefinitionReplaceError,
13    GraphPropertiesError,
14    GraphTraverseError,
15    VertexCollectionCreateError,
16    VertexCollectionDeleteError,
17    VertexCollectionListError,
18)
19from arango.executor import ApiExecutor
20from arango.formatter import format_graph_properties
21from arango.request import Request
22from arango.response import Response
23from arango.result import Result
24from arango.typings import Json, Jsons
25from arango.utils import get_col_name, get_doc_id
26
27
28class Graph(ApiGroup):
29    """Graph API wrapper."""
30
31    def __init__(
32        self, connection: Connection, executor: ApiExecutor, name: str
33    ) -> None:
34        super().__init__(connection, executor)
35        self._name = name
36
37    def __repr__(self) -> str:
38        return f"<Graph {self._name}>"
39
40    def _get_col_by_vertex(self, vertex: Union[str, Json]) -> VertexCollection:
41        """Return the vertex collection for the given vertex document.
42
43        :param vertex: Vertex document ID or body with "_id" field.
44        :type vertex: str | dict
45        :return: Vertex collection API wrapper.
46        :rtype: arango.collection.VertexCollection
47        """
48        return self.vertex_collection(get_col_name(vertex))
49
50    def _get_col_by_edge(self, edge: Union[str, Json]) -> EdgeCollection:
51        """Return the edge collection for the given edge document.
52
53        :param edge: Edge document ID or body with "_id" field.
54        :type edge: str | dict
55        :return: Edge collection API wrapper.
56        :rtype: arango.collection.EdgeCollection
57        """
58        return self.edge_collection(get_col_name(edge))
59
60    @property
61    def name(self) -> str:
62        """Return the graph name.
63
64        :return: Graph name.
65        :rtype: str
66        """
67        return self._name
68
69    def properties(self) -> Result[Json]:
70        """Return graph properties.
71
72        :return: Graph properties.
73        :rtype: dict
74        :raise arango.exceptions.GraphPropertiesError: If retrieval fails.
75        """
76        request = Request(method="get", endpoint=f"/_api/gharial/{self._name}")
77
78        def response_handler(resp: Response) -> Json:
79            if resp.is_success:
80                return format_graph_properties(resp.body["graph"])
81            raise GraphPropertiesError(resp, request)
82
83        return self._execute(request, response_handler)
84
85    ################################
86    # Vertex Collection Management #
87    ################################
88
89    def has_vertex_collection(self, name: str) -> Result[bool]:
90        """Check if the graph has the given vertex collection.
91
92        :param name: Vertex collection name.
93        :type name: str
94        :return: True if vertex collection exists, False otherwise.
95        :rtype: bool
96        """
97        request = Request(
98            method="get",
99            endpoint=f"/_api/gharial/{self._name}/vertex",
100        )
101
102        def response_handler(resp: Response) -> bool:
103            if resp.is_success:
104                return name in resp.body["collections"]
105            raise VertexCollectionListError(resp, request)
106
107        return self._execute(request, response_handler)
108
109    def vertex_collections(self) -> Result[List[str]]:
110        """Return vertex collections in the graph that are not orphaned.
111
112        :return: Names of vertex collections that are not orphaned.
113        :rtype: [str]
114        :raise arango.exceptions.VertexCollectionListError: If retrieval fails.
115        """
116        request = Request(
117            method="get",
118            endpoint=f"/_api/gharial/{self._name}/vertex",
119        )
120
121        def response_handler(resp: Response) -> List[str]:
122            if not resp.is_success:
123                raise VertexCollectionListError(resp, request)
124            return sorted(set(resp.body["collections"]))
125
126        return self._execute(request, response_handler)
127
128    def vertex_collection(self, name: str) -> VertexCollection:
129        """Return the vertex collection API wrapper.
130
131        :param name: Vertex collection name.
132        :type name: str
133        :return: Vertex collection API wrapper.
134        :rtype: arango.collection.VertexCollection
135        """
136        return VertexCollection(self._conn, self._executor, self._name, name)
137
138    def create_vertex_collection(self, name: str) -> Result[VertexCollection]:
139        """Create a vertex collection in the graph.
140
141        :param name: Vertex collection name.
142        :type name: str
143        :return: Vertex collection API wrapper.
144        :rtype: arango.collection.VertexCollection
145        :raise arango.exceptions.VertexCollectionCreateError: If create fails.
146        """
147        request = Request(
148            method="post",
149            endpoint=f"/_api/gharial/{self._name}/vertex",
150            data={"collection": name},
151        )
152
153        def response_handler(resp: Response) -> VertexCollection:
154            if resp.is_success:
155                return self.vertex_collection(name)
156            raise VertexCollectionCreateError(resp, request)
157
158        return self._execute(request, response_handler)
159
160    def delete_vertex_collection(self, name: str, purge: bool = False) -> Result[bool]:
161        """Remove a vertex collection from the graph.
162
163        :param name: Vertex collection name.
164        :type name: str
165        :param purge: If set to True, the vertex collection is not just deleted
166            from the graph but also from the database completely.
167        :type purge: bool
168        :return: True if vertex collection was deleted successfully.
169        :rtype: bool
170        :raise arango.exceptions.VertexCollectionDeleteError: If delete fails.
171        """
172        request = Request(
173            method="delete",
174            endpoint=f"/_api/gharial/{self._name}/vertex/{name}",
175            params={"dropCollection": purge},
176        )
177
178        def response_handler(resp: Response) -> bool:
179            if resp.is_success:
180                return True
181            raise VertexCollectionDeleteError(resp, request)
182
183        return self._execute(request, response_handler)
184
185    ##############################
186    # Edge Collection Management #
187    ##############################
188
189    def has_edge_definition(self, name: str) -> Result[bool]:
190        """Check if the graph has the given edge definition.
191
192        :param name: Edge collection name.
193        :type name: str
194        :return: True if edge definition exists, False otherwise.
195        :rtype: bool
196        """
197        request = Request(method="get", endpoint=f"/_api/gharial/{self._name}")
198
199        def response_handler(resp: Response) -> bool:
200            if not resp.is_success:
201                raise EdgeDefinitionListError(resp, request)
202
203            body = resp.body["graph"]
204            return any(
205                edge_definition["collection"] == name
206                for edge_definition in body["edgeDefinitions"]
207            )
208
209        return self._execute(request, response_handler)
210
211    def has_edge_collection(self, name: str) -> Result[bool]:
212        """Check if the graph has the given edge collection.
213
214        :param name: Edge collection name.
215        :type name: str
216        :return: True if edge collection exists, False otherwise.
217        :rtype: bool
218        """
219        return self.has_edge_definition(name)
220
221    def edge_collection(self, name: str) -> EdgeCollection:
222        """Return the edge collection API wrapper.
223
224        :param name: Edge collection name.
225        :type name: str
226        :return: Edge collection API wrapper.
227        :rtype: arango.collection.EdgeCollection
228        """
229        return EdgeCollection(self._conn, self._executor, self._name, name)
230
231    def edge_definitions(self) -> Result[Jsons]:
232        """Return the edge definitions of the graph.
233
234        :return: Edge definitions of the graph.
235        :rtype: [dict]
236        :raise arango.exceptions.EdgeDefinitionListError: If retrieval fails.
237        """
238        request = Request(method="get", endpoint=f"/_api/gharial/{self._name}")
239
240        def response_handler(resp: Response) -> Jsons:
241            if not resp.is_success:
242                raise EdgeDefinitionListError(resp, request)
243
244            body = resp.body["graph"]
245            return [
246                {
247                    "edge_collection": edge_definition["collection"],
248                    "from_vertex_collections": edge_definition["from"],
249                    "to_vertex_collections": edge_definition["to"],
250                }
251                for edge_definition in body["edgeDefinitions"]
252            ]
253
254        return self._execute(request, response_handler)
255
256    def create_edge_definition(
257        self,
258        edge_collection: str,
259        from_vertex_collections: Sequence[str],
260        to_vertex_collections: Sequence[str],
261    ) -> Result[EdgeCollection]:
262        """Create a new edge definition.
263
264        An edge definition consists of an edge collection, "from" vertex
265        collection(s) and "to" vertex collection(s). Here is an example entry:
266
267        .. code-block:: python
268
269            {
270                'edge_collection': 'edge_collection_name',
271                'from_vertex_collections': ['from_vertex_collection_name'],
272                'to_vertex_collections': ['to_vertex_collection_name']
273            }
274
275        :param edge_collection: Edge collection name.
276        :type edge_collection: str
277        :param from_vertex_collections: Names of "from" vertex collections.
278        :type from_vertex_collections: [str]
279        :param to_vertex_collections: Names of "to" vertex collections.
280        :type to_vertex_collections: [str]
281        :return: Edge collection API wrapper.
282        :rtype: arango.collection.EdgeCollection
283        :raise arango.exceptions.EdgeDefinitionCreateError: If create fails.
284        """
285        request = Request(
286            method="post",
287            endpoint=f"/_api/gharial/{self._name}/edge",
288            data={
289                "collection": edge_collection,
290                "from": from_vertex_collections,
291                "to": to_vertex_collections,
292            },
293        )
294
295        def response_handler(resp: Response) -> EdgeCollection:
296            if resp.is_success:
297                return self.edge_collection(edge_collection)
298            raise EdgeDefinitionCreateError(resp, request)
299
300        return self._execute(request, response_handler)
301
302    def replace_edge_definition(
303        self,
304        edge_collection: str,
305        from_vertex_collections: Sequence[str],
306        to_vertex_collections: Sequence[str],
307    ) -> Result[EdgeCollection]:
308        """Replace an edge definition.
309
310        :param edge_collection: Edge collection name.
311        :type edge_collection: str
312        :param from_vertex_collections: Names of "from" vertex collections.
313        :type from_vertex_collections: [str]
314        :param to_vertex_collections: Names of "to" vertex collections.
315        :type to_vertex_collections: [str]
316        :return: Edge collection API wrapper.
317        :rtype: arango.collection.EdgeCollection
318        :raise arango.exceptions.EdgeDefinitionReplaceError: If replace fails.
319        """
320        request = Request(
321            method="put",
322            endpoint=f"/_api/gharial/{self._name}/edge/{edge_collection}",
323            data={
324                "collection": edge_collection,
325                "from": from_vertex_collections,
326                "to": to_vertex_collections,
327            },
328        )
329
330        def response_handler(resp: Response) -> EdgeCollection:
331            if resp.is_success:
332                return self.edge_collection(edge_collection)
333            raise EdgeDefinitionReplaceError(resp, request)
334
335        return self._execute(request, response_handler)
336
337    def delete_edge_definition(self, name: str, purge: bool = False) -> Result[bool]:
338        """Delete an edge definition from the graph.
339
340        :param name: Edge collection name.
341        :type name: str
342        :param purge: If set to True, the edge definition is not just removed
343            from the graph but the edge collection is also deleted completely
344            from the database.
345        :type purge: bool
346        :return: True if edge definition was deleted successfully.
347        :rtype: bool
348        :raise arango.exceptions.EdgeDefinitionDeleteError: If delete fails.
349        """
350        request = Request(
351            method="delete",
352            endpoint=f"/_api/gharial/{self._name}/edge/{name}",
353            params={"dropCollections": purge},
354        )
355
356        def response_handler(resp: Response) -> bool:
357            if resp.is_success:
358                return True
359            raise EdgeDefinitionDeleteError(resp, request)
360
361        return self._execute(request, response_handler)
362
363    ###################
364    # Graph Functions #
365    ###################
366
367    def traverse(
368        self,
369        start_vertex: Union[str, Json],
370        direction: str = "outbound",
371        item_order: str = "forward",
372        strategy: Optional[str] = None,
373        order: Optional[str] = None,
374        edge_uniqueness: Optional[str] = None,
375        vertex_uniqueness: Optional[str] = None,
376        max_iter: Optional[int] = None,
377        min_depth: Optional[int] = None,
378        max_depth: Optional[int] = None,
379        init_func: Optional[str] = None,
380        sort_func: Optional[str] = None,
381        filter_func: Optional[str] = None,
382        visitor_func: Optional[str] = None,
383        expander_func: Optional[str] = None,
384    ) -> Result[Json]:
385        """Traverse the graph and return the visited vertices and edges.
386
387        :param start_vertex: Start vertex document ID or body with "_id" field.
388        :type start_vertex: str | dict
389        :param direction: Traversal direction. Allowed values are "outbound"
390            (default), "inbound" and "any".
391        :type direction: str
392        :param item_order: Item iteration order. Allowed values are "forward"
393            (default) and "backward".
394        :type item_order: str
395        :param strategy: Traversal strategy. Allowed values are "depthfirst"
396            and "breadthfirst".
397        :type strategy: str | None
398        :param order: Traversal order. Allowed values are "preorder",
399            "postorder", and "preorder-expander".
400        :type order: str | None
401        :param edge_uniqueness: Uniqueness for visited edges. Allowed values
402            are "global", "path" or "none".
403        :type edge_uniqueness: str | None
404        :param vertex_uniqueness: Uniqueness for visited vertices. Allowed
405            values are "global", "path" or "none".
406        :type vertex_uniqueness: str | None
407        :param max_iter: If set, halt the traversal after the given number of
408            iterations. This parameter can be used to prevent endless loops in
409            cyclic graphs.
410        :type max_iter: int | None
411        :param min_depth: Minimum depth of the nodes to visit.
412        :type min_depth: int | None
413        :param max_depth: Maximum depth of the nodes to visit.
414        :type max_depth: int | None
415        :param init_func: Initialization function in Javascript with signature
416            ``(config, result) -> void``. This function is used to initialize
417            values in the result.
418        :type init_func: str | None
419        :param sort_func: Sorting function in Javascript with signature
420            ``(left, right) -> integer``, which returns ``-1`` if ``left <
421            right``, ``+1`` if ``left > right`` and ``0`` if ``left == right``.
422        :type sort_func: str | None
423        :param filter_func: Filter function in Javascript with signature
424            ``(config, vertex, path) -> mixed``, where ``mixed`` can have one
425            of the following values (or an array with multiple): "exclude" (do
426            not visit the vertex), "prune" (do not follow the edges of the
427            vertex), or "undefined" (visit the vertex and follow its edges).
428        :type filter_func: str | None
429        :param visitor_func: Visitor function in Javascript with signature
430            ``(config, result, vertex, path, connected) -> void``. The return
431            value is ignored, ``result`` is modified by reference, and
432            ``connected`` is populated only when parameter **order** is set to
433            "preorder-expander".
434        :type visitor_func: str | None
435        :param expander_func: Expander function in Javascript with signature
436            ``(config, vertex, path) -> mixed``. The function must return an
437            array of connections for ``vertex``. Each connection is an object
438            with attributes "edge" and "vertex".
439        :type expander_func: str | None
440        :return: Visited edges and vertices.
441        :rtype: dict
442        :raise arango.exceptions.GraphTraverseError: If traversal fails.
443        """
444        if strategy is not None:
445            if strategy.lower() == "dfs":
446                strategy = "depthfirst"
447            elif strategy.lower() == "bfs":
448                strategy = "breadthfirst"
449
450        uniqueness = {}
451        if vertex_uniqueness is not None:
452            uniqueness["vertices"] = vertex_uniqueness
453        if edge_uniqueness is not None:
454            uniqueness["edges"] = edge_uniqueness
455
456        data: Json = {
457            "startVertex": get_doc_id(start_vertex),
458            "graphName": self._name,
459            "direction": direction,
460            "strategy": strategy,
461            "order": order,
462            "itemOrder": item_order,
463            "uniqueness": uniqueness or None,
464            "maxIterations": max_iter,
465            "minDepth": min_depth,
466            "maxDepth": max_depth,
467            "init": init_func,
468            "filter": filter_func,
469            "visitor": visitor_func,
470            "sort": sort_func,
471            "expander": expander_func,
472        }
473        request = Request(
474            method="post",
475            endpoint="/_api/traversal",
476            data={k: v for k, v in data.items() if v is not None},
477        )
478
479        def response_handler(resp: Response) -> Json:
480            if not resp.is_success:
481                raise GraphTraverseError(resp, request)
482
483            result: Json = resp.body["result"]["visited"]
484            return result
485
486        return self._execute(request, response_handler)
487
488    #####################
489    # Vertex Management #
490    #####################
491
492    def has_vertex(
493        self,
494        vertex: Union[str, Json],
495        rev: Optional[str] = None,
496        check_rev: bool = True,
497    ) -> Result[bool]:
498        """Check if the given vertex document exists in the graph.
499
500        :param vertex: Vertex document ID or body with "_id" field.
501        :type vertex: str | dict
502        :param rev: Expected document revision. Overrides the value of "_rev"
503            field in **vertex** if present.
504        :type rev: str | None
505        :param check_rev: If set to True, revision of **vertex** (if given) is
506            compared against the revision of target vertex document.
507        :type check_rev: bool
508        :return: True if vertex document exists, False otherwise.
509        :rtype: bool
510        :raise arango.exceptions.DocumentGetError: If check fails.
511        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
512        """
513        return self._get_col_by_vertex(vertex).has(vertex, rev, check_rev)
514
515    def vertex(
516        self,
517        vertex: Union[str, Json],
518        rev: Optional[str] = None,
519        check_rev: bool = True,
520    ) -> Result[Optional[Json]]:
521        """Return a vertex document.
522
523        :param vertex: Vertex document ID or body with "_id" field.
524        :type vertex: str | dict
525        :param rev: Expected document revision. Overrides the value of "_rev"
526            field in **vertex** if present.
527        :type rev: str | None
528        :param check_rev: If set to True, revision of **vertex** (if given) is
529            compared against the revision of target vertex document.
530        :type check_rev: bool
531        :return: Vertex document or None if not found.
532        :rtype: dict | None
533        :raise arango.exceptions.DocumentGetError: If retrieval fails.
534        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
535        """
536        return self._get_col_by_vertex(vertex).get(vertex, rev, check_rev)
537
538    def insert_vertex(
539        self,
540        collection: str,
541        vertex: Json,
542        sync: Optional[bool] = None,
543        silent: bool = False,
544    ) -> Result[Union[bool, Json]]:
545        """Insert a new vertex document.
546
547        :param collection: Vertex collection name.
548        :type collection: str
549        :param vertex: New vertex document to insert. If it has "_key" or "_id"
550            field, its value is used as key of the new vertex (otherwise it is
551            auto-generated). Any "_rev" field is ignored.
552        :type vertex: dict
553        :param sync: Block until operation is synchronized to disk.
554        :type sync: bool | None
555        :param silent: If set to True, no document metadata is returned. This
556            can be used to save resources.
557        :type silent: bool
558        :return: Document metadata (e.g. document key, revision) or True if
559            parameter **silent** was set to True.
560        :rtype: bool | dict
561        :raise arango.exceptions.DocumentInsertError: If insert fails.
562        """
563        return self.vertex_collection(collection).insert(vertex, sync, silent)
564
565    def update_vertex(
566        self,
567        vertex: Json,
568        check_rev: bool = True,
569        keep_none: bool = True,
570        sync: Optional[bool] = None,
571        silent: bool = False,
572    ) -> Result[Union[bool, Json]]:
573        """Update a vertex document.
574
575        :param vertex: Partial or full vertex document with updated values. It
576            must contain the "_id" field.
577        :type vertex: dict
578        :param check_rev: If set to True, revision of **vertex** (if given) is
579            compared against the revision of target vertex document.
580        :type check_rev: bool
581        :param keep_none: If set to True, fields with value None are retained
582            in the document. If set to False, they are removed completely.
583        :type keep_none: bool
584        :param sync: Block until operation is synchronized to disk.
585        :type sync: bool | None
586        :param silent: If set to True, no document metadata is returned. This
587            can be used to save resources.
588        :type silent: bool
589        :return: Document metadata (e.g. document key, revision) or True if
590            parameter **silent** was set to True.
591        :rtype: bool | dict
592        :raise arango.exceptions.DocumentUpdateError: If update fails.
593        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
594        """
595        return self._get_col_by_vertex(vertex).update(
596            vertex=vertex,
597            check_rev=check_rev,
598            keep_none=keep_none,
599            sync=sync,
600            silent=silent,
601        )
602
603    def replace_vertex(
604        self,
605        vertex: Json,
606        check_rev: bool = True,
607        sync: Optional[bool] = None,
608        silent: bool = False,
609    ) -> Result[Union[bool, Json]]:
610        """Replace a vertex document.
611
612        :param vertex: New vertex document to replace the old one with. It must
613            contain the "_id" field.
614        :type vertex: dict
615        :param check_rev: If set to True, revision of **vertex** (if given) is
616            compared against the revision of target vertex document.
617        :type check_rev: bool
618        :param sync: Block until operation is synchronized to disk.
619        :type sync: bool | None
620        :param silent: If set to True, no document metadata is returned. This
621            can be used to save resources.
622        :type silent: bool
623        :return: Document metadata (e.g. document key, revision) or True if
624            parameter **silent** was set to True.
625        :rtype: bool | dict
626        :raise arango.exceptions.DocumentReplaceError: If replace fails.
627        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
628        """
629        return self._get_col_by_vertex(vertex).replace(
630            vertex=vertex, check_rev=check_rev, sync=sync, silent=silent
631        )
632
633    def delete_vertex(
634        self,
635        vertex: Json,
636        rev: Optional[str] = None,
637        check_rev: bool = True,
638        ignore_missing: bool = False,
639        sync: Optional[bool] = None,
640    ) -> Result[Union[bool, Json]]:
641        """Delete a vertex document.
642
643        :param vertex: Vertex document ID or body with "_id" field.
644        :type vertex: str | dict
645        :param rev: Expected document revision. Overrides the value of "_rev"
646            field in **vertex** if present.
647        :type rev: str | None
648        :param check_rev: If set to True, revision of **vertex** (if given) is
649            compared against the revision of target vertex document.
650        :type check_rev: bool
651        :param ignore_missing: Do not raise an exception on missing document.
652            This parameter has no effect in transactions where an exception is
653            always raised on failures.
654        :type ignore_missing: bool
655        :param sync: Block until operation is synchronized to disk.
656        :type sync: bool | None
657        :return: True if vertex was deleted successfully, False if vertex was
658            not found and **ignore_missing** was set to True (does not apply in
659            transactions).
660        :rtype: bool
661        :raise arango.exceptions.DocumentDeleteError: If delete fails.
662        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
663        """
664        return self._get_col_by_vertex(vertex).delete(
665            vertex=vertex,
666            rev=rev,
667            check_rev=check_rev,
668            ignore_missing=ignore_missing,
669            sync=sync,
670        )
671
672    ###################
673    # Edge Management #
674    ###################
675
676    def has_edge(
677        self, edge: Union[str, Json], rev: Optional[str] = None, check_rev: bool = True
678    ) -> Result[bool]:
679        """Check if the given edge document exists in the graph.
680
681        :param edge: Edge document ID or body with "_id" field.
682        :type edge: str | dict
683        :param rev: Expected document revision. Overrides the value of "_rev"
684            field in **edge** if present.
685        :type rev: str | None
686        :param check_rev: If set to True, revision of **edge** (if given) is
687            compared against the revision of target edge document.
688        :type check_rev: bool
689        :return: True if edge document exists, False otherwise.
690        :rtype: bool
691        :raise arango.exceptions.DocumentInError: If check fails.
692        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
693        """
694        return self._get_col_by_edge(edge).has(edge, rev, check_rev)
695
696    def edge(
697        self, edge: Union[str, Json], rev: Optional[str] = None, check_rev: bool = True
698    ) -> Result[Optional[Json]]:
699        """Return an edge document.
700
701        :param edge: Edge document ID or body with "_id" field.
702        :type edge: str | dict
703        :param rev: Expected document revision. Overrides the value of "_rev"
704            field in **edge** if present.
705        :type rev: str | None
706        :param check_rev: If set to True, revision of **edge** (if given) is
707            compared against the revision of target edge document.
708        :type check_rev: bool
709        :return: Edge document or None if not found.
710        :rtype: dict | None
711        :raise arango.exceptions.DocumentGetError: If retrieval fails.
712        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
713        """
714        return self._get_col_by_edge(edge).get(edge, rev, check_rev)
715
716    def insert_edge(
717        self,
718        collection: str,
719        edge: Json,
720        sync: Optional[bool] = None,
721        silent: bool = False,
722    ) -> Result[Union[bool, Json]]:
723        """Insert a new edge document.
724
725        :param collection: Edge collection name.
726        :type collection: str
727        :param edge: New edge document to insert. It must contain "_from" and
728            "_to" fields. If it has "_key" or "_id" field, its value is used
729            as key of the new edge document (otherwise it is auto-generated).
730            Any "_rev" field is ignored.
731        :type edge: dict
732        :param sync: Block until operation is synchronized to disk.
733        :type sync: bool | None
734        :param silent: If set to True, no document metadata is returned. This
735            can be used to save resources.
736        :type silent: bool
737        :return: Document metadata (e.g. document key, revision) or True if
738            parameter **silent** was set to True.
739        :rtype: bool | dict
740        :raise arango.exceptions.DocumentInsertError: If insert fails.
741        """
742        return self.edge_collection(collection).insert(edge, sync, silent)
743
744    def update_edge(
745        self,
746        edge: Json,
747        check_rev: bool = True,
748        keep_none: bool = True,
749        sync: Optional[bool] = None,
750        silent: bool = False,
751    ) -> Result[Union[bool, Json]]:
752        """Update an edge document.
753
754        :param edge: Partial or full edge document with updated values. It must
755            contain the "_id" field.
756        :type edge: dict
757        :param check_rev: If set to True, revision of **edge** (if given) is
758            compared against the revision of target edge document.
759        :type check_rev: bool
760        :param keep_none: If set to True, fields with value None are retained
761            in the document. If set to False, they are removed completely.
762        :type keep_none: bool | None
763        :param sync: Block until operation is synchronized to disk.
764        :type sync: bool | None
765        :param silent: If set to True, no document metadata is returned. This
766            can be used to save resources.
767        :type silent: bool
768        :return: Document metadata (e.g. document key, revision) or True if
769            parameter **silent** was set to True.
770        :rtype: bool | dict
771        :raise arango.exceptions.DocumentUpdateError: If update fails.
772        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
773        """
774        return self._get_col_by_edge(edge).update(
775            edge=edge,
776            check_rev=check_rev,
777            keep_none=keep_none,
778            sync=sync,
779            silent=silent,
780        )
781
782    def replace_edge(
783        self,
784        edge: Json,
785        check_rev: bool = True,
786        sync: Optional[bool] = None,
787        silent: bool = False,
788    ) -> Result[Union[bool, Json]]:
789        """Replace an edge document.
790
791        :param edge: New edge document to replace the old one with. It must
792            contain the "_id" field. It must also contain the "_from" and "_to"
793            fields.
794        :type edge: dict
795        :param check_rev: If set to True, revision of **edge** (if given) is
796            compared against the revision of target edge document.
797        :type check_rev: bool
798        :param sync: Block until operation is synchronized to disk.
799        :type sync: bool | None
800        :param silent: If set to True, no document metadata is returned. This
801            can be used to save resources.
802        :type silent: bool
803        :return: Document metadata (e.g. document key, revision) or True if
804            parameter **silent** was set to True.
805        :rtype: bool | dict
806        :raise arango.exceptions.DocumentReplaceError: If replace fails.
807        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
808        """
809        return self._get_col_by_edge(edge).replace(
810            edge=edge, check_rev=check_rev, sync=sync, silent=silent
811        )
812
813    def delete_edge(
814        self,
815        edge: Union[str, Json],
816        rev: Optional[str] = None,
817        check_rev: bool = True,
818        ignore_missing: bool = False,
819        sync: Optional[bool] = None,
820    ) -> Result[Union[bool, Json]]:
821        """Delete an edge document.
822
823        :param edge: Edge document ID or body with "_id" field.
824        :type edge: str | dict
825        :param rev: Expected document revision. Overrides the value of "_rev"
826            field in **edge** if present.
827        :type rev: str | None
828        :param check_rev: If set to True, revision of **edge** (if given) is
829            compared against the revision of target edge document.
830        :type check_rev: bool
831        :param ignore_missing: Do not raise an exception on missing document.
832            This parameter has no effect in transactions where an exception is
833            always raised on failures.
834        :type ignore_missing: bool
835        :param sync: Block until operation is synchronized to disk.
836        :type sync: bool | None
837        :return: True if edge was deleted successfully, False if edge was not
838            found and **ignore_missing** was set to True (does not  apply in
839            transactions).
840        :rtype: bool
841        :raise arango.exceptions.DocumentDeleteError: If delete fails.
842        :raise arango.exceptions.DocumentRevisionError: If revisions mismatch.
843        """
844        return self._get_col_by_edge(edge).delete(
845            edge=edge,
846            rev=rev,
847            check_rev=check_rev,
848            ignore_missing=ignore_missing,
849            sync=sync,
850        )
851
852    def link(
853        self,
854        collection: str,
855        from_vertex: Union[str, Json],
856        to_vertex: Union[str, Json],
857        data: Optional[Json] = None,
858        sync: Optional[bool] = None,
859        silent: bool = False,
860    ) -> Result[Union[bool, Json]]:
861        """Insert a new edge document linking the given vertices.
862
863        :param collection: Edge collection name.
864        :type collection: str
865        :param from_vertex: "From" vertex document ID or body with "_id" field.
866        :type from_vertex: str | dict
867        :param to_vertex: "To" vertex document ID or body with "_id" field.
868        :type to_vertex: str | dict
869        :param data: Any extra data for the new edge document. If it has "_key"
870            or "_id" field, its value is used as key of the new edge document
871            (otherwise it is auto-generated).
872        :type data: dict
873        :param sync: Block until operation is synchronized to disk.
874        :type sync: bool | None
875        :param silent: If set to True, no document metadata is returned. This
876            can be used to save resources.
877        :type silent: bool
878        :return: Document metadata (e.g. document key, revision) or True if
879            parameter **silent** was set to True.
880        :rtype: bool | dict
881        :raise arango.exceptions.DocumentInsertError: If insert fails.
882        """
883        return self.edge_collection(collection).link(
884            from_vertex=from_vertex,
885            to_vertex=to_vertex,
886            data=data,
887            sync=sync,
888            silent=silent,
889        )
890
891    def edges(
892        self, collection: str, vertex: Union[str, Json], direction: Optional[str] = None
893    ) -> Result[Json]:
894        """Return the edge documents coming in and/or out of given vertex.
895
896        :param collection: Edge collection name.
897        :type collection: str
898        :param vertex: Vertex document ID or body with "_id" field.
899        :type vertex: str | dict
900        :param direction: The direction of the edges. Allowed values are "in"
901            and "out". If not set, edges in both directions are returned.
902        :type direction: str
903        :return: List of edges and statistics.
904        :rtype: dict
905        :raise arango.exceptions.EdgeListError: If retrieval fails.
906        """
907        return self.edge_collection(collection).edges(vertex, direction)
908