19.2. Core API

19.2.1. Getting started
19.2.2. Transactions
19.2.3. Nodes
19.2.4. Relationships
19.2.5. Properties
19.2.6. Paths

This section describes how get get up and running, and how to do basic operations.

19.2.1. Getting started

Creating a database

from neo4j import GraphDatabase

# Create db
db = GraphDatabase(folder_to_put_db_in)

# Always shut down your database
db.shutdown()

Creating a database, with configuration

Please see Chapter 21, Configuration & Performance for what options you can use here.

from neo4j import GraphDatabase

# Example configuration parameters
db = GraphDatabase(folder_to_put_db_in, string_block_size=200, array_block_size=240)

db.shutdown()

JPype JVM configuration

You can set extra arguments to be passed to the JVM using the NEO4J_PYTHON_JVMARGS environment variable. This can be used to, for instance, increase the max memory for the database.

Note that you must set this before you import the neo4j package, either by setting it before you start python, or by setting it programatically in your app.

import os
os.environ['NEO4J_PYTHON_JVMARGS'] = '-Xms128M -Xmx512M'
import neo4j

You can also override the classpath used by neo4j-embedded, by setting the NEO4J_PYTHON_CLASSPATH environment variable.

19.2.2. Transactions

All write operations to the database need to be performed from within transactions. This ensures that your database never ends up in an inconsistent state.

See Chapter 13, Transaction Management for details on how Neo4j handles transactions.

We use the python with statement to define a transaction context. If you are using an older version of Python, you may have to import the with statement:

from __future__ import with_statement

Either way, this is how you get into a transaction:

# Start a transaction
with db.transaction:
    # This is inside the transactional
    # context. All work done here
    # will either entirely succeed,
    # or no changes will be applied at all.

    # Create a node
    node = db.node()

    # Give it a name
    node['name'] = 'Cat Stevens'

# The transaction is automatically
# commited when you exit the with
# block.

19.2.3. Nodes

This describes operations that are specific to node objects. For documentation on how to handle properties on both relationships and nodes, see Section 19.2.5, “Properties”.

Creating a node

with db.transaction:
    # Create a node
    thomas = db.node(name='Thomas Anderson', age=42)

Fetching a node by id

# You don't have to be in a transaction
# to do read operations.
a_node = db.node[some_node_id]

# Ids on nodes and relationships are available via the "id"
# property, eg.:
node_id = a_node.id

Fetching the reference node

reference = db.reference_node

Removing a node

with db.transaction:
    node = db.node()
    node.delete()

Removing a node by id

with db.transaction:
    del db.node[some_node_id]

Accessing relationships from a node

For details on what you can do with the relationship objects, see Section 19.2.4, “Relationships”.

# All relationships on a node
for rel in a_node.relationships:
    pass

# Incoming relationships
for rel in a_node.relationships.incoming:
    pass

# Outgoing relationships
for rel in a_node.relationships.outgoing:
    pass

# Relationships of a specific type
for rel in a_node.mayor_of:
    pass

# Incoming relationships of a specific type
for rel in a_node.mayor_of.incoming:
    pass

# Outgoing relationships of a specific type
for rel in a_node.mayor_of.outgoing:
    pass

Getting and/or counting all nodes

Use this with care, it will become extremely slow in large datasets.

for node in db.nodes:
    pass

# Shorthand for iterating through
# and counting all nodes
number_of_nodes = len(db.nodes)

19.2.4. Relationships

This describes operations that are specific to relationship objects. For documentation on how to handle properties on both relationships and nodes, see Section 19.2.5, “Properties”.

Creating a relationship

with db.transaction:
    # Nodes to create a relationship between
    steven = self.graphdb.node(name='Steve Brook')
    poplar_bluff = self.graphdb.node(name='Poplar Bluff')

    # Create a relationship of type "mayor_of"
    relationship = steven.mayor_of(poplar_bluff, since="12th of July 2012")

    # Or, to create relationship types with names
    # that would not be possible with the above
    # method.
    steven.relationships.create('mayor_of', poplar_bluff, since="12th of July 2012")

Fetching a relationship by id

the_relationship = db.relationship[a_relationship_id]

Removing a relationship

with db.transaction:
    # Create a relationship
    source = db.node()
    target = db.node()
    rel = source.Knows(target)

    # Delete it
    rel.delete()

Removing a relationship by id

with db.transaction:
    del db.relationship[some_relationship_id]

Relationship start node, end node and type

relationship_type = relationship.type

start_node = relationship.start
end_node = relationship.end

Getting and/or counting all relationships

Use this with care, it will become extremely slow in large datasets.

for rel in db.relationships:
    pass

# Shorthand for iterating through
# and counting all relationships
number_of_rels = len(db.relationships)

19.2.5. Properties

Both nodes and relationships can have properties, so this section applies equally to both node and relationship objects. Allowed property values include strings, numbers, booleans, as well as arrays of those primitives. Within each array, all values must be of the same type.

Setting properties

with db.transaction:
    node_or_rel['name'] = 'Thomas Anderson'
    node_or_rel['age'] = 42
    node_or_rel['favourite_numbers'] = [1,2,3]
    node_or_rel['favourite_words'] = ['banana','blue']

Getting properties

numbers = node_or_rel['favourite_numbers']

Removing properties

with db.transaction:
    del node_or_rel['favourite_numbers']

Looping through properties

# Loop key and value at the same time
for key, value in node_or_rel.items():
    pass

# Loop property keys
for key in node_or_rel.keys():
    pass

# Loop property values
for value in node_or_rel.values():
    pass

19.2.6. Paths

A path object represents a path between two nodes in the graph. Paths thus contain at least two nodes and one relationship, but can reach arbitrary length. It is used in various parts of the API, most notably in traversals.

Accessing the start and end nodes

start_node = path.start
end_node = path.end

Accessing the last relationship

last_relationship = path.last_relationship

Looping through the entire path

You can loop through all elements of a path directly, or you can choose to only loop through nodes or relationships. When you loop through all elements, the first item will be the start node, the second will be the first relationship, the third the node that the relationship led to and so on.

for item in path:
    # Item is either a Relationship,
    # or a Node
    pass

for nodes in path.nodes:
    # All nodes in a path
    pass

for nodes in path.relationships:
    # All relationships in a path
    pass