Using Goblin

Goblin aims to provide an easy to use, intuitive API, without sacrificing the flexibility enabled by extensive user configuration. It is designed to ‘just work’ out of the box with most versions of Python (2.7+) using the tornado.ioloop.IOLoop and tornado.concurrent.Future class. But as the Python community moves forward with projects like asyncio, trollius, aiohttp (based on asyncio), and curio, developers want to be able to choose the async API, event loop and future implementation that works with their stack. To enable this, Goblin provides a pluggable client implementation that allows the user to choose the client, event loop, and future classes, provided that certain compatibility and API requirements are kept in mind.

This document aims to present an overview of the core functionality of Goblin in the simplest manner possible. In future versions, each of these sections will be expanded into a guide covering the complete functionality provided by Goblin. For a full reference, please see the API docs.

Setting up Goblin

In order to talk to the Gremlin Server, Goblin needs a Future, which can be any future implementation with a compatible API, and a Pool, which is typically inherits from gremlinclient.Pool. For a simple application, you can use goblin.connection.setup(), which allows you to define a Future and Pool as goblin.connection constants that will be used throughout Goblin:

>>> import asyncio
>>> from gremlinclient import aiohttp_client
>>> from goblin import connection

>>> connection.setup(
...     pool_class=aiohttp_client.Pool, future_class=asyncio.Future)

The function goblin.connection.setup() provides a wide variety of configuration options, please refer to the API docs for a complete description.

For more involved applications, it is often desirable to manage connection pool and futures explicitly. Goblin allows these parameters to be passed as keyword arguments to any caller of goblin.connection.execute_query().

After using goblin.connection.setup(), it is important to call goblin.connection.tear_down() to clean up any remaining connections. Depending on the connection pool implementation, this method may or may not return a Future. Using gremlinclient.aiohttp_client.Pool:

>>> yield from connection.tear_down()

All of the following examples assume a gremlinclient.aiohttp_client.Pool and asyncio.Future

Creating models

The core functionality of Goblin lies in the models module, which allows you to define Python classes (vertices, edges, and properties) that are mapped to graph elements.

using the Gremlin query language:

>>> from goblin import models
>>> from goblin import properties

>>> class User(models.Vertex):
...     name = properties.String()
...     email = properties.Email()
...     url = properties.Url()

>>> class Follows(models.Edge):
        pass  # Edge can have properties just like Vertex

We can then use the method create to create nodes and edges:

>>> joe = yield from User.create(name='joe', email='joe@joe.com',
...                              url='http://joe.com')
>>> bob = yield from User.create(name='bob', email='bob@bob.com',
...                              url='http://bob.com')
>>> joe_follows_bob = yield from Follows.create(joe, bob)

This creates two vertices with the label “user” and one edge with the label “follows” in the graphdb.

Elements can be retrieved from the graphdb using class methods provided by the element implementations. These methods include get which allows you to retrieve an element by id, and all, which retrieves all elements with a label corresponding to the model class from the database:

>>> joe = yield from User.get(joe.id)
>>> users = yield from User.all()

Instances of graph elements (Vertices and Edges) provide methods that allow you to delete and update properties.

>>> josep = yield from joe.save(name='Josep')
>>> yield from josep.delete()

Graph element instances also provide an API that allows you to access and modify neighbor elements, but this API is under review and may be deprecated in favor of the vertex centric query API and the proposed edge centric query API.

Using the Relationship class

In an effort to provide a more convenient API, Goblin provides the Relationship class, which allows you to explicitly define relationships between vertex classes:

>>> from goblin import models
>>> from goblin import properties
>>> from goblin import relationships

>>> class WorksIn(models.Edge):
        pass

>>> class Department(models.Vertex):
...     name = properties.String()

>>> class Employee(models.Vertex)
...     name = properties.String()
...     email = properties.Email()
...     department = relationships.Relationship(WorksIn, Department)

You can then use the department relationship to easily create edges of type WorksIn and vertices of type Department:

>>> joe = Employee.create(name='joe', email="joe@joe.com")
>>> joe_works_in, r_and_d = yield from joe.department.create(
...     vertex_params={'name': 'R&D'})

The Relationship class provides several other methods for convenience as well. For a full reference, please see the API docs

The V ertex centric query API

To emulate Gremlin style traversals, Goblin provides the class V, which provides an interface for step based graph traversals using method chaining. Unlike Gremlin, the class V requires that the user pass a vertex or vertex id as a starting point for the traversal. For example:

>>> from goblin.models import V
>>> dep = yield from V(joe).out_step().get()
>>> r_and_d = yield from V(joe).\
...     out_step().\
...     has(Department.get_property_by_name('name'), 'R&D').\
...     get()

There are three things to note in the above example:

  1. The Gremlin steps in and out have been renamed as in_step and out_step due to the fact that in is a reserved word in Python
  2. All traversal must end with get.
  3. The has step requires that you use get_property_by_name() method to retrieve the correct property key.

Furthermore, it should be noted that the camel case used in Gremlin steps has been replaced with the underscores more commonly used with Python methods: inV -> in_v.

For a full list of steps, please see the API docs

Coming soon, detailed guides...