Quickstart¶
Basic Python examples for how to use Bulbs with Neo4j Server.
Before you begin, make sure you download and install Bulbs and Neo4j Server.
Neo4j Server¶
Bulbs’ Neo4j Server client is a Python interface to the Neo4j Server REST API.
To use Bulbs with Neo4j Server, you need to make sure Neo4j Server is up and running.
Start Neo4j Server¶
Change to the directory where you installed Neo4j Server, and start it with its default configuration:
$ cd /path/to/neo4j-<version>
$ bin/neo4j start
Browse Neo4j Server¶
Now check to see that you can browse the Neo4j Web admin using this URL:
If you can, then success! Neo4j Server is up and running.
The Neo4j Web Admin is a browser-based interface to Neo4j Server that allows you to view elements in the graph and simulate a Gremlin-console session. See the Neo4j Tools documentation for details.
Graph¶
Ok, now the fun part. This will show you how to use Bulbs to connect to Neo4j Server from Python and interact with the graph database.
Create the Graph Object¶
Here’s how you create the Graph object, your primary interface to Neo4j Server:
>>> from bulbs.neo4jserver import Graph
>>> g = Graph()
If you don’t pass a Config object to Graph(), Graph will use the default URI and Config.
You you can pass in a custom config, with a uri, username, and password (a username and password is not required by default):
>>> from bulbs.neo4jserver import Graph, Config, NEO4J_URI
>>> config = Config(NEO4J_URI, "james", "secret")
>>> g = Graph(config)
We used the default Neo4j URI:
>>> print NEO4J_URI
If you ever change the URI in the server config, you should use your URI instead:
>>> config = Config('http://example.dev:7777/db/data/')
>>> g = Graph(config)
Create Vertices and Edges¶
Here is a basic example that creates two Vertex objects and an Edge object that links them together:
>>> james = g.vertices.create(name="James")
>>> julie = g.vertices.create(name="Julie")
>>> g.edges.create(james, "knows", julie)
Return a Property¶
>>> james.name
Update an Existing Property¶
>>> james.name = "James Thornton"
>>> james.save()
Add New Properties¶
>>> james.city = "Dallas"
>>> james.age = 34
>>> james.save()
Return the Property Data Map¶
>>> james.data()
Get Vertex by ID¶
>>> james.eid
1
>>> james2 = g.vertices.get(1)
>>> assert james == james2
Update Vertex by ID¶
>>> data = dict(age=34, city="Dallas")
>>> g.vertices.update(1, data)
Display Vertices¶
Display all the vertices in the graph:
>>> g.V
This returns a list all the Vertex objects in the graph.
This method is primarily used for testing because you won’t normally want to do this for a large database containing millions (or billions) of vertices.
You can see how many vertices were returned by checking the length of the list:
>>> vertices = g.V
>>> len(vertices)
Display Edges¶
Display all the edges in the graph:
>>> g.E
Like g.V, this method is primarily used for testing because you won’t normally want to do this for a large database.
Look Up Indexed Vertices¶
The default Bulbs Config class has autoindex set to True, with “vertex” as the name of the default Vertex index. When autoindex is True, it will automatically index vertices when you create or update them.
Everytime you create a new vertex, it’s automatically added to vertex index, and you can look it up by its properties.
This will return all the vertices that have a “name” property with a value of “James”:
>>> g.vertices.index.lookup(name="James")
As you can see, the return value is a Python generator.
A generator is iterable like a list, but it’s more memory friendly because it’s not copying the entire list around – it lazy loads items as needed:
>>> vertices = g.vertices.index.lookup(name="James")
>>> for vertex in vertices: print vertex
Get the next Vertex in the generator:
>>> vertices = g.vertices.index.lookup(name="James")
>>> james = vertices.next()
To convert a generator into a list, do this:
>>> vertices = g.vertices.index.lookup(name="James")
>>> list(vertices)
Get Adjacent Edges¶
Get all outgoing edges:
>>> james.outE()
Get outgoing edges labeled “knows”:
>>> james.outE("knows")
Get incoming edges (there shouldn’t be any):
>>> james.inE()
Get all the incoming and outgoing edges:
>>> james.bothE()
Get Adjacent Vertices¶
An adjacent vertex is a vertex connected to another vertex by an edge.
Get all the outgoing vertices:
>>> james.outV()
Get outgoing vertices connected by edges labeled “knows”:
>>> james.outV("knows")
Get incoming vertices (there shouldn’t be any):
>>> james.inV()
Get all the incoming and outgoing vertices:
>>> james.bothV()
Enable Debugging¶
Bulbs uses the Python logging facility, and by default it sets the logger to use StreamHandler with log level set to ERROR
To display DEBUG info, set the log level to DEBUG:
>>> from bulbs.config import DEBUG
>>> g.config.set_logger(DEBUG)
Disable Debugging¶
To disable DEBUG info, set the log level back to ERROR:
>>> from bulbs.config import ERROR
>>> g.config.set_logger(ERROR)
Models¶
Model Declaration¶
You can also use Bulbs to create type-checked, domain-specific models:
# people.py
from bulbs.model import Node, Relationship
from bulbs.property import String, Integer, DateTime
from bulbs.utils import current_datetime
class Person(Node):
element_type = "person"
name = String(nullable=False)
age = Integer()
class Knows(Relationship):
label = "knows"
created = DateTime(default=current_datetime, nullable=False)
Example Usage¶
Models provide type checking and validation to ensure that your database properties are stored properly.
Here’s how you would use the models to create and connect Person objects:
>>> from people import Person, Knows
>>> from bulbs.neo4jserver import Graph
>>> g = Graph()
Add proxy interfaces to the Graph object for each custom Model:
>>> g.add_proxy("people", Person)
>>> g.add_proxy("knows", Knows)
Create two Person nodes, which are automatically saved in the DB:
>>> james = g.people.create(name="James")
>>> julie = g.people.create(name="Julie")
Lookup people using the Person model’s primary index:
>>> nodes = g.people.index.lookup(name="James")
Connect James and Julie by creating a “knows” relationship between them:
>>> relationship = g.knows.create(james, julie)
Get the people James knows (the outgoing vertices labeled “knows”):
>>> friends = james.outV('knows')
Get the people that know Julie (the incoming vertices labeled “knows”):
>>> friends = julie.inV('knows')
Return the relationship element’s ID:
>>> relationship.eid
Return the created property:
>>> relationship.created
Return all the property data:
>>> relationship.data()
Return the label:
>>> relationship.label()
Return the outgoing vertex:
>>> relationship.outV()
Return the incoming vertex:
>>> relationship.inV()
Return the outgoing vertex ID:
>>> relationship._outV
Return the incoming vertex ID:
>>> relationship._inV
Gremlin¶
Using the Neo4j Web console is sometimes convienent, but most of the time I use the external Gremlin REPL to experiment with queries.
Create a neo4j.groovy file with the path to your neo4j/data/graph.db directory:
// neo4j.groovy
import org.neo4j.kernel.EmbeddedReadOnlyGraphDatabase
db = new EmbeddedReadOnlyGraphDatabase('/path/to/neo4j/data/graph.db')
g = new Neo4jGraph(db)
And then load neo4j.groovy when you start a Gremlin REPL:
$ cd /path/to/gremlin
$ ./gremlin.sh
\,,,/
(o o)
-----oOOo-(_)-oOOo-----
gremlin> load neo4j.groovy
gremlin> g.V.range(0,9) // try viewing the first 10 vertices in the graph