Skip to content

Adding more documentation #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
Python driver for [ArangoDB](https://www.arangodb.com), a scalable multi-model
database natively supporting documents, graphs and search.

This is the _asyncio_ alternative of the officially supported [python-arango](https://github.com/arangodb/python-arango)
This is the _asyncio_ alternative of the [python-arango](https://github.com/arangodb/python-arango)
driver.

**Note: This project is still in active development, features might be added or removed.**

## Requirements

- ArangoDB version 3.11+
- Python version 3.9+
- Python version 3.10+

## Installation

Expand Down
5 changes: 5 additions & 0 deletions arangoasync/aql.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ def name(self) -> str:
"""Return the name of the current database."""
return self._executor.db_name

@property
def context(self) -> str:
"""Return the current API execution context."""
return self._executor.context

@property
def serializer(self) -> Serializer[Json]:
"""Return the serializer."""
Expand Down
29 changes: 27 additions & 2 deletions arangoasync/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,15 @@ def name(self) -> str:
"""
return self._name

@property
def context(self) -> str:
"""Return the context of the collection.

Returns:
str: Context.
"""
return self._executor.context

@property
def db_name(self) -> str:
"""Return the name of the current database.
Expand All @@ -270,9 +279,17 @@ def deserializer(self) -> Deserializer[Json, Jsons]:
"""Return the deserializer."""
return self._executor.deserializer

async def indexes(self) -> Result[List[IndexProperties]]:
async def indexes(
self,
with_stats: Optional[bool] = None,
with_hidden: Optional[bool] = None,
) -> Result[List[IndexProperties]]:
"""Fetch all index descriptions for the given collection.

Args:
with_stats (bool | None): Whether to include figures and estimates in the result.
with_hidden (bool | None): Whether to include hidden indexes in the result.

Returns:
list: List of index properties.

Expand All @@ -282,10 +299,16 @@ async def indexes(self) -> Result[List[IndexProperties]]:
References:
- `list-all-indexes-of-a-collection <https://docs.arangodb.com/stable/develop/http-api/indexes/#list-all-indexes-of-a-collection>`__
""" # noqa: E501
params: Params = dict(collection=self._name)
if with_stats is not None:
params["withStats"] = with_stats
if with_hidden is not None:
params["withHidden"] = with_hidden

request = Request(
method=Method.GET,
endpoint="/_api/index",
params=dict(collection=self._name),
params=params,
)

def response_handler(resp: Response) -> List[IndexProperties]:
Expand Down Expand Up @@ -564,6 +587,7 @@ async def get(
Raises:
DocumentRevisionError: If the revision is incorrect.
DocumentGetError: If retrieval fails.
DocumentParseError: If the document is malformed.

References:
- `get-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#get-a-document>`__
Expand Down Expand Up @@ -707,6 +731,7 @@ async def insert(

Raises:
DocumentInsertError: If insertion fails.
DocumentParseError: If the document is malformed.

References:
- `create-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#create-a-document>`__
Expand Down
3 changes: 3 additions & 0 deletions arangoasync/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ async def process_request(self, request: Request) -> Response:
host_index = self._host_resolver.get_host_index()
for tries in range(self._host_resolver.max_tries):
try:
logger.debug(
f"Sending request to host {host_index} ({tries}): {request}"
)
resp = await self._http_client.send_request(
self._sessions[host_index], request
)
Expand Down
4 changes: 0 additions & 4 deletions arangoasync/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,6 @@ async def create_collection(
)

def response_handler(resp: Response) -> StandardCollection[T, U, V]:
nonlocal doc_serializer, doc_deserializer
if not resp.is_success:
raise CollectionCreateError(resp, request)
if doc_serializer is None:
Expand Down Expand Up @@ -648,7 +647,6 @@ async def delete_collection(
)

def response_handler(resp: Response) -> bool:
nonlocal ignore_missing
if resp.is_success:
return True
if resp.status_code == HTTP_NOT_FOUND and ignore_missing:
Expand Down Expand Up @@ -1001,7 +999,6 @@ async def update_permission(
)

def response_handler(resp: Response) -> bool:
nonlocal ignore_failure
if resp.is_success:
return True
if ignore_failure:
Expand Down Expand Up @@ -1046,7 +1043,6 @@ async def reset_permission(
)

def response_handler(resp: Response) -> bool:
nonlocal ignore_failure
if resp.is_success:
return True
if ignore_failure:
Expand Down
165 changes: 163 additions & 2 deletions docs/aql.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,167 @@ AQL
to SQL for relational databases, but without the support for data definition
operations such as creating or deleting :doc:`databases <database>`,
:doc:`collections <collection>` or :doc:`indexes <indexes>`. For more
information, refer to `ArangoDB manual`_.
information, refer to `ArangoDB Manual`_.

.. _ArangoDB manual: https://docs.arangodb.com
.. _ArangoDB Manual: https://docs.arangodb.com

AQL Queries
===========

AQL queries are invoked from AQL wrapper. Executing queries returns
:doc:`cursors <cursor>`.

**Example:**

.. code-block:: python

from arangoasync import ArangoClient, AQLQueryKillError
from arangoasync.auth import Auth

# Initialize the client for ArangoDB.
async with ArangoClient(hosts="http://localhost:8529") as client:
auth = Auth(username="root", password="passwd")

# Connect to "test" database as root user.
db = await client.db("test", auth=auth)

# Get the API wrapper for "students" collection.
students = db.collection("students")

# Insert some test documents into "students" collection.
await students.insert_many([
{"_key": "Abby", "age": 22},
{"_key": "John", "age": 18},
{"_key": "Mary", "age": 21}
])

# Get the AQL API wrapper.
aql = db.aql

# Retrieve the execution plan without running the query.
plan = await aql.explain("FOR doc IN students RETURN doc")

# Validate the query without executing it.
validate = await aql.validate("FOR doc IN students RETURN doc")

# Execute the query
cursor = await db.aql.execute(
"FOR doc IN students FILTER doc.age < @value RETURN doc",
bind_vars={"value": 19}
)

# Iterate through the result cursor
student_keys = []
async for doc in cursor:
student_keys.append(doc)

# List currently running queries.
queries = await aql.queries()

# List any slow queries.
slow_queries = await aql.slow_queries()

# Clear slow AQL queries if any.
await aql.clear_slow_queries()

# Retrieve AQL query tracking properties.
await aql.tracking()

# Configure AQL query tracking properties.
await aql.set_tracking(
max_slow_queries=10,
track_bind_vars=True,
track_slow_queries=True
)

# Kill a running query (this should fail due to invalid ID).
try:
await aql.kill("some_query_id")
except AQLQueryKillError as err:
assert err.http_code == 404

See :class:`arangoasync.aql.AQL` for API specification.


AQL User Functions
==================

**AQL User Functions** are custom functions you define in Javascript to extend
AQL functionality. They are somewhat similar to SQL procedures.

**Example:**

.. code-block:: python

from arangoasync import ArangoClient
from arangoasync.auth import Auth

# Initialize the client for ArangoDB.
async with ArangoClient(hosts="http://localhost:8529") as client:
auth = Auth(username="root", password="passwd")

# Connect to "test" database as root user.
db = await client.db("test", auth=auth)

# Get the AQL API wrapper.
aql = db.aql

# Create a new AQL user function.
await aql.create_function(
# Grouping by name prefix is supported.
name="functions::temperature::converter",
code="function (celsius) { return celsius * 1.8 + 32; }"
)

# List AQL user functions.
functions = await aql.functions()

# Delete an existing AQL user function.
await aql.delete_function("functions::temperature::converter")

See :class:`arangoasync.aql.AQL` for API specification.


AQL Query Cache
===============

**AQL Query Cache** is used to minimize redundant calculation of the same query
results. It is useful when read queries are issued frequently and write queries
are not.

**Example:**

.. code-block:: python

from arangoasync import ArangoClient
from arangoasync.auth import Auth

# Initialize the client for ArangoDB.
async with ArangoClient(hosts="http://localhost:8529") as client:
auth = Auth(username="root", password="passwd")

# Connect to "test" database as root user.
db = await client.db("test", auth=auth)

# Get the AQL API wrapper.
aql = db.aql

# Retrieve AQL query cache properties.
await aql.cache.properties()

# Configure AQL query cache properties.
await aql.cache.configure(mode="demand", max_results=10000)

# List results cache entries.
entries = await aql.cache.entries()

# List plan cache entries.
plan_entries = await aql.cache.plan_entries()

# Clear results in AQL query cache.
await aql.cache.clear()

# Clear results in AQL query plan cache.
await aql.cache.clear_plan()

See :class:`arangoasync.aql.AQLQueryCache` for API specification.
Loading
Loading