========================================== py4neo :: A Python REST client for Neo4j ========================================== :synopsis: Allows interact with Neo4j standalone REST server from Python. :heritage: py4neo is a fork of neo4j-rest-client_ py4neo provides a Pythonic interface to interacting with graphs stored in Neo4j. It relies on Neo4j's REST interface. Its API is compatibile with neo4j.py_, which means current applications should be able to seamlessly migrate. py4neo attempts to place an emphasis on interacting with the graph as the main data structure. It is compatibile with ``neo4j-rest-client``, however it provides a number of convience methods to increase the elegance of the code. Future versions will attempt to create an interface to NetworkX_. Usage ===== Note: This guide assumes that you are running Ubuntu_ with a bash shell. However, there should be very little difference between operating systems. Starting the graph server ------------------------- To begin, start the Neo4j server:: $ /path/to/neo4j/bin/neo4j start You are now able to use py4neo with your applications. Graphs ------ Mirroring neo4j.py_, the main class you is *GraphDatabase*:: >>> from client import GraphDatabase >>> graphdb = GraphDatabase("http://localhost:7474/db/data/") Two global options are available:: client.CACHE = False # Default client.DEBUG = False # Default If ``client.CACHE`` is ``True``, then a .cache directory will be created. It will be populated as nodes are queried, and future requests to the same URL will be taken from cache. When ``client.DEBUG`` is ``True``, ``httplib2`` is set to debuglevel = 1. This will assist with debugging networking issues. Nodes, Relationships and Properties ---------------------------------- Creating a node:: >>> n = graphdb.node() >>> n = graphdb.nodes.create() #equivalent Specify properties for new node:: >>> n = graphdb.node(color="Red", widht=16, height=32) >>> n = graphdb.nodes.create(color="Red", widht=16, height=32) #equivalent Accessing nodes:: >>> graphdb[14] >>> graphdb.node[14] >>> graphdb.nodes.get(14) Accessing properties:: >>> n['color'] "Red" >>> n['color'] = "Blue" >>> del n['color'] # Or the other way >>> value = n.get('key', 'default') # Supports 'default' values >>> n.set('key', value) >>> n.delete('key') Node objects have other attributes:: >>> n.properties {} >>> n.properties = {'name': 'John'} {'name': 'John'} # The URL and the identifier assigned by Neo4j are added too >>> n.id 14 >>> n.url 'http://localhost:7474/db/data/node/14' Creating relationships ---------------------- The simplest way to create a relationship is to use the attribute syntax. Capitalisation is a Neo4j convention to indicate a relationship:: >>> anna = graphdb.node(name="Anna") >>> bill = graphdb.node(name="Bill") >>> anna.KNOWS(bill) All graphs in Neo4j are directed. This means that reciprocial relationships must be created explicitly. Sometimes it's useful to store relationship names as variables or use complex keys. This is not handled very well by Python's attribute syntax, so you should use the underlying methods:: >>> knows = "KNOWS" >>> anna.relationships.create(knows, bill) Relationships can also have properties:: >>> anna.KNOWS(bill, since=123456789, introduced_at="Christmas party") >>> bill.relationships.create("KNOWS", anna, since=123456789, introduced_at="Christmas party") Relationship attributes: ------------------------ >>> bill = n1.relationships.create("DISLIKES", anna, since=123456789) >>> rel.start <Neo4j Node: http://localhost:7474/db/data/node/14> >>> rel.end <Neo4j Node: http://localhost:7474/db/data/node/32> >>> rel.type 'DISLIKES' >>> rel.properties {'since': 123456789} Retrieving a node's relationships --------------------------------- Use a node.relationship's all method to get every relationship associated with that node. This includes both incoming and outgoing relationships:: >>> anna.relationships.all() #doctest: +ELLIPSIS [<Neo4j Relationship: http://localhost:7474/db/data/relationship/...>, ...] To restrict this to a particular type, add the desired types as a list to the types argument:: >>> anna.relationships.all(types=["IS_CAUTIOUS_OF"]) #doctest: +ELLIPSIS [] It is possible to refine this further to retrieve incoming or outgoing relationships. >>> anna.relationships.incoming(types=["KNOWS"]) #doctest: +ELLIPSIS [<Neo4j Relationship: http://localhost:7474/db/data/relationship/...>, ...] >>> rels = n1.relationships.outgoing(["KNOWS", "LOVES"]) [<Neo4j Relationship: http://localhost:7474/db/data/relationship/35842>, <Neo4j Relationship: http://localhost:7474/db/data/relationship/35847>] Traversals ---------- Traversals through the graph are supported too with the same syntax of neo4j.py_:: >>> class TraversalClass(gdb.Traversal): ... types = [Undirected.Knows] py4neo also provides an alternate syntax:: >>> n1.traverse(types=[client.Undirected.Knows]) [<Neo4j Node: http://localhost:7474/db/data/node/15880>] Transactions ------------ Neo4j's REST server lacks transactions. .. _neo4j.py: http://components.neo4j.org/neo4j.py/ .. _neo4j-rest-client: https://github.com/versae/neo4j-rest-client .. _Ubuntu: http://www.ubuntu.com/ .. _NetworkX: http://networkx.lanl.gov/