Py2neo is a Python library that provides object-oriented access to Neo4j graph databases using REST bindings. It allows Python applications to connect to Neo4j, create and retrieve nodes and relationships, run Cypher queries, and interact with the graph database in a simple way. The presentation introduces the basic py2neo concepts like connecting to Neo4j, creating and querying nodes and relationships, using indexes, running Cypher queries, and exporting data to different formats like CSV, JSON, and Geoff. Future plans for py2neo include adding features like fast HTTP, multi-threading support, and new methods.
6. Default Connections
>>> from py2neo import neo4j
>>> graph_db = neo4j.GraphDatabaseService()
default connection is made to
<http://localhost:7474/db/data/>
8. A few simple methods...
>>> graph_db.get_node(0)
Node('http://localhost:7474/db/data/node/0')
>>> graph_db.get_reference_node()
Node('http://localhost:7474/db/data/node/0')
>>> graph_db.get_node_count()
1
>>> graph_db.get_relationship_count()
0
9. Sample data: a family tree
m
(1947)
Phil (1921) Liz (1926)
Chaz (1948) Anne (1950) Andy (1960) Ed (1964)
All characters appearing in this work are fictitious. Any resemblance to
real persons, living or dead, is purely coincidental.
10. list of nodes
create
nodes = graph_db.create(
Phil Liz
{"name": "Phil", "born": 1921},
{"name": "Liz", "born": 1926},
{"name": "Chaz", "born": 1948},
{"name": "Anne", "born": 1950}, Chaz Anne
{"name": "Andy", "born": 1960},
{"name": "Ed", "born": 1964},
) Andy Ed
11. list of
relationships create
MARRIED
rels = graph_db.create( Phil Liz
(phil, "MARRIED", liz),
(chaz, "FATHER", phil), FATHER MOTHER
(chaz, "MOTHER", liz),
Chaz
)
node must
already exist
16. PropertyContainers
implement many of the
container methods defined
by the Python standard
<http://docs.python.org/reference/datamodel.html#emulating-container-types>
17. neo4j.PropertyContainer
set property
# update properties
liz["star_sign"] = "Taurus"
# query properties get property
test property
for node in nodes: containment
name = node["name"]
if "star_sign" in node:
print name + " is a node["star_sign"]
else:
print name + " doesn't believe in horoscopes"
28. Indexing the first family...
>>> people = graph_db.get_or_create_index(neo4j.Node, "People")
>>> for node in nodes:
... people.add("name", node["name"], node)
>>> people.get("name", "Liz")
[Node('http://localhost:7474/db/data/node/2')]
list of matching
entities
29. ...and the second
>>> new_props = [
... {"name": "George", "born": 1895},
... {"name": "Betty", "born": 1900},
... {"name": "Liz", "born": 1926},
... {"name": "Maggie", "born": 1930},
... ]
>>> george, betty, liz, maggie = [
... people.get_or_create("name", prop["name"], prop)
... for prop in new_props same node
... ] as before
>>> people.get("name", "Liz")
[Node('http://localhost:7474/db/data/node/2')]
30. A Quick Query
>>> people.query("name:*e*")
[Node('http://localhost:7474/db/data/node/4'),
Node('http://localhost:7474/db/data/node/7'),
Node('http://localhost:7474/db/data/node/8'),
Node('http://localhost:7474/db/data/node/9')]
People
George
name Andy
name Anne
Maggie
name Betty
name Chaz
name Ed
name George Anne
name Liz
name Maggie
Betty
name Phil
37. cypher.execute
>>> from py2neo import cypher
>>> query = "START q=node(1) RETURN q"
>>> data, metadata = cypher.execute(graph_db, query)
>>> for row in data:
... q = row[0]
... print q
first column
38. cypher.execute
>>> from py2neo import cypher
>>> query = "START q=node(1) RETURN q"
>>> data, metadata = cypher.execute(graph_db, query)
available only after
all rows received
>>> for row in data:
... q = row[0]
... print q
first column
39. cypher.execute
query = "START q=node(1) RETURN q"
executed once
per row as each
def print_row(row): row is received
q = row[0]
print row
cypher.execute(graph_db, query, row_handler=print_row)
40. Command Line Cypher
elgin@forge:~% cypher "start a=node(1) match (a)-[:MARRIED]->(b) return a, b"
+------------------------------------------------------------------+
| a | b |
+------------------------------------------------------------------+
| (1) {"name":"Phil","born":1921} | (2) {"name":"Liz","born":1926} |
+------------------------------------------------------------------+
elgin@forge:~% cypher -f csv "start a=node(1) match (a)-[ab:MARRIED]->(b) return a, ab, b"
"a","ab","b"
"(1)","(1)-[0:MARRIED]->(2)","(2)"
elgin@forge:~% cypher -f json "start a=node(1) match (a)-[ab:MARRIED]->(b) return a, ab, b"
[
{"a": "(1)", "ab": "(1)-[0:MARRIED]->(2)", "b": "(2)"}
]
elgin@forge:~% cypher -f geoff "start a=node(1) match (a)-[ab:MARRIED]->(b) return a, ab, b"
(1) {"name": "Phil", "born": 1921}
(2) {"name": "Liz", "born": 1926}
(1)-[0:MARRIED]->(2) {"year": 1947, "place": "London"}
41. Geoff is to graph data
as
CSV is to tabular data
<http://geoff.nigelsmall.net/>
48. Future Plans
●
Fast HTTP
●
Multi-threading support
●
Python 3
●
Command line tools
●
Property caching
●
Test harness for multiple Neo4j versions
●
New methods, e.g. get_paths_to