Welcome to AjguDB Documentation

Kesako?!

AjguDB is graph database written in Python with several backends. It's meant to be an easy to use, just works persistent graph for people that want to experiment with graph databases. SQLite for graphs, if I may.

Getting started

Create a Graph

You need to choose a storage class and create a graph. There is three storages right now:

You can start graphology as easily as:

from ajgu import Database
from ajgu import BSDDB3


graph = Database(BSDDB3('/path/to/my/super-dupper/database/files'))

If the directory doesn't exists it will be created.

Remember to close the database, when you are finished:

graph.close()

The Mighty Transaction

Every operation must happen in a transaction. For that matter there is a context manager Graph.transaction() that returns a storage specific transaction class. It must be used as follow:

with graph.transaction() as txn:
    txn.vertex.create('my-vertex')
    ...
    ...

The transaction will be commited if there is no error.

For advanced use, you can use Graph.txn() method to create a transaction and manage it yourself. It looks like the following:

try:
    txn = graph.txn()
    txn.create_vertex('my-vertex')
    ...
    ...
except Exception as exc:
    txn.rollback()
else:
    txn.commit()

commit and rollback are the only public methods of transaction class.

Both Graph.transaction and Graph.txn take keyword arguments to configure the transaction. It depends of the backend. Read the code to know more about the options.

Create a vertex

The transaction object works as a shadow copy of the graph. Otherwise said, its methods reflects the graph structure. You always perform graph operations against it. Once the transaction is commited, changes are persisted and saved.

To create a vertex use Transaction.vertex.create(label):

with graph.transaction() as txn:
    amirouche = txn.vertex.create('amirouche')
    amirouche.properties['age'] = 30

As you can see in the above snippet it's possible to add properties to a vertex through the properties attribute just like you do with a normal dictionary. Values can be anything that can be serialized by msgpack: int, float, str, list, dict and any combination of them.

Vertex are indexed by their Vertex.label(). Several vertices can have the same label.

Create an edge

To create an edge you can use Transaction.edge.create(start, label, end):

with graph.transaction() as txn:
    amirouche = txn.vertex.create("amirouche")
    python = txn.vertex.create("python")
    txn.edge.create(amirouche 'know', python)

Edge have also an index on their label, also available as Edge.label(). Labels don't have be unique either. start and end must be vertices created or retrieve in the current transaction. You can also edit edge's properties via Edge.properties attribute.

Transaction.*.get

You can retrieve edge with Transaction.edge.get(identifier) and vertices with Transaction.vertex.get(identifier.

Vertices outgoing and incoming edges

Vertex has Vertex.outgoings(label=None) and Vertex.incomings(label=None). They allow to retrieve edges. The label argument allows to filter based on the edge.label() of the edge. They return a generator. They will be explained further below.

Quering

Even querying happens against the transaction. Querying happens through what is called managers, available at transaction.vertex and transaction.edge. Here the lists of their methods:

transaction.element.all()

Return a generator over all elements of a given type.

transaction.element.count()

Return the count of objects for a given type.

transaction.element.slice(start, end)

Return a slice of of elements between start and end (excluded) indices.

transaction.element.label(label)

Return a generator over all elements of the given type filtered by label. You can chain an operator over the given generator using the following syntax transaction.element.slice.operator where operator can be slice, count or first.

transaction.element.filter(key=value)

Return a generator over all the element of the given type filtered by property name key and value. You can chain an operator over the given generator using the following syntax transaction.element.slice.operator where operator can be slice, count or first.

Only properties that are indexed can be filtered

To create an index over key use Graph.index(key). This will index every elements (edge and vertex) with the a property.

transaction.element.get(**kwargs)

Return a generator over all elements of the given type filtered by kwargs you can chain an operator over the given generator using the following syntax transaction.element.slice.operator where operator can be slice, count or first.

Mind the fact that right now only one pair of key/value is supported kwargs providing more pairs won't refine the query.

transaction.element.get(identifier)

That one we've already seen allow to retrieve an object by identifier.

transaction.element.create(...)

This one too was presented previously allow to create an element of given type. The signature is different depending on the actual type.