Package: neo4py
Neo4j Python Bindings========================:synopsis: Access Neo4j graph database functionality from python codeOnly tested with Neo4j 1.3 on OSX Snow Leopard, Python 2.6Notice------This is a work in progress.  Please let me know if stuff in this document fails or doesn't seem to be true.Thanks much.Installation------------Install JCC:$ easy_install jccDownload and unpack neo4j somewhere (http://neo4j.org/download/)Currently only version 1.3 is supportedSet NEO4J_HOME environment variable to this download of Neo4j:$ export NEO4J_HOME=~/downloads/neo4j-community-1.3Enter the Neo4py package directory:$ cd the/directory/with/this/readmeBuild C++ wrappers with JCC:$ python setup.py buildInstall (may require sudo-ness):$ python setup.py installRun some tests:$ python test/test_graph_core.pyHopefully no errors!  If there are, send me the tracebacks :)Getting started---------------Simplest way is to use the 'global' graph.>>> from neo4py import neo>>> gdb = neo.init_graph('test-graph.neo4j')>>> gdb.shutdown()This global graph may be accessed from anywhere after being initialized with>>> gdb = neo.get_graph()Transactions------------Transactions are handled differently than in neo4j.py>>> tx, created = gdb.get_tx()If created is True, it is the responsibility of this scope to commit the transaction when done it:>>> tx.finish(True)	# success - commit changes to database>>> tx.finish(False)	# failure - rollback changes>>> tx.success()		# or .failure()>>> tx.finish()		# it doesn't matter if True of False is passed here -- it will be ignoredNodes, Relationships and Properties (Beginning of fun stuff)----------------------------------** Not all syntax is neo4j.py compatible **Creating a node::			(must be within a transaction!)>>> n = gdb.node()Specify properties for new node::>>> n = gdb.node(petals=5, color="Red", height=5.5)			#support for number or string array properties is not yet addedAccessing node by id:>>> n = gdb.nodes[14]Accessing properties:>>> value = n['key'] # Get property value>>> n['key'] = value # Set property value>>> del n['key']     # Remove property value# Or, with a default>>> value = n.get('key', 'default')>>> for prop in n: do_something(prop)>>> for prop, value in n.iteritems(): do_someting(prop,value)		# loop through node properties>>>more_props = { "name" : "Jack", "occupation" : "Pilot" }>>>n1.update(more_props)>>>n2.update(name="Sarah", occupation="Astronaut")>>> n.id	# Node idCreate relationship::>>> n1.Knows(n2, since="A long time ago")# Or>>> n1.relationships("Likes")(n2, how_much="A lot") 	# Usefull when the name of# relationship is stored in a variable.# This syntax may change though... seems obscure?The creation returns a Relationship object, which has properties accessible like nodes.>>> rel = n1.Knows(n2, since=123456789)>>> rel['since']123456789Additional attributes:>>> rel.start		# start node (n1)>>> rel.end		# end node (n2)>>> rel.type'Knows'Others functions over 'relationships' attribute are possible. Like get all,incoming or outgoing relationships (typed or not):>>> rels = list(n1.relationships())>>> rels = list(n1.relationships("Knows", "Likes").incoming)>>> rel = n1.Knows.outgoing.singleTraversals----------In progress.  Much like neo4j.pySee tests (neo4py/testing/graph_core.py)>>> from neo4py.core import Direction>>> from neo4py.traversal import Traverser, Stop, Returnable, Orderclass MyTraverser(Traverser):types = [Direction.Incoming.Knows, Direction.Undirected.Likes]is_stop = lambda pos: pos.node == my_node		#can use a python method		####  LARGELY UNTESTED  #####pos is a TraversalPosition objectis_returnable = Returnable.ALL			#or a java defined ReturnableEvaluator/StopEvaluator# (these are faster)order = Order.DEPTH_FIRSTIndices-------See tests (neo4py/testing/graph_core.py)>>> node_idx = gdb.node_indices.create("My node index", fulltext=True)		#create an new fulltext index#Will fail index with name already exists>>> node_idx = gdb.node_indices["My node index"]			#retrieve already created index>>> "That index" in gdb.node_indices					#test if index existsFalse>>> "My node index" in gdb.node_indicesTrue>>> rel_idx = gdb.rel_indices.create("Relationship index")		# works the same, but for relationships>>> node_idx['name', "Jack"] = n1>>> node_idx['name', "Jack"] = n500			# two nodes indexed under 'name' => "Jack">>>nodes = list(node_idx['name', 'Jack'])		# Returns iterator over both nodes (exact matching using this syntax)>>>nodes = list(node_idx.simple_query('name', 'jack')	# fulltext query by single key/value>>>nodes = list(node_idx.query('name:jack'))		# Run lucene query (supports multiple keys)Relationship indices same, but with a couple extra options (See Neo4j Docs):>>> rels = list(rel_idx.simple_query('key', 'value', start_node=n1)		#limit query, for efficiency (can also be end_node)>>> rels = list(rel_idx.query('key:value', end_node=some_other_node)Models, Django support, QuerySets, Aggregates------In Progress