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:
- 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
- All traversal must end with
get
. - 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...