Friday, September 27, 2013

Py2neo 1.6

Hi all,
It's a weird thought that although Neo4j has been part of my life for well over two years, I've only met in person a few of the people that I know from its community. Thanks to the wonderful generosity of Emil and co though, that will soon change as I'll be jetting over to San Francisco for Graph Connect, giving me a chance to meet both the Neo guys and my fellow driver authors.

The timing is also pretty good as I've just released Py2neo 1.6 which introduces one of the most requested features of recent months: node labels. As most Neophiles will know, labels allow nodes to be tagged with keywords that can be used for categorisation and indexing. Adding labels to a node in Py2neo is straightforward with the add_labels method:

>>> from py2neo import neo4j, node
>>> graph_db = neo4j.GraphDatabaseService()
>>> alice, = graph_db.create(node(name="Alice"))
>>> alice.add_labels("Female", "Human")

The set_labels and remove_labels methods similarly allow labels to be replaced or deleted and get_labels returns the set of labels currently defined. The GraphDatabaseService.find method can then be used to gather up all the nodes with a particular label and iterate through them:

>>> for node in graph_db.find("Human"):
...     print node["name"]

Aside from labels, the biggest change in the 1.6 release is a complete rewrite of the underlying HTTP/REST mechanism. In order to achieve better support for streaming responses, it was necessary to rip out the simple mechanism that had been with Py2neo since the early days and build a more comprehensive layer from the ground up. Incremental JSON decoding is a key feature that allows server responses to be handled step by step instead of only after the response has been completely received. This new layer has grown into a separate project, HTTPStream, but is embedded into Py2neo to avoid dependencies.

But what advantages does HTTPStream give to Py2neo-based applications? Well, it's now possible to incrementally handle the results of Cypher queries and batch requests as well as those from a few other functions, such as match. These functions now provide result iterators instead of full result objects. Here's an example of a Cypher query streamed against the data inserted above:

>>> query = neo4j.CypherQuery(graph_db, "MATCH (being:Human) RETURN being")
>>> for result in query.stream():
...     print result.being["name"]

Neotool has received some love too. The command line variant of Py2neo now fully supports Unicode, provides facilities for Cypher execution, Geoff insertion and XML conversion as well as options for HTTP authentication. The diagram below shows the conversion paths now available:


For a quick demonstration of the XML conversion feature in action, check out this web service. Another good place for a good neotool overview is my recent lightning talk from the London Graph Café.

So what isn't included? Cypher transactions are the main omission from the Neo4j 2.0 feature set and have been deliberately left out until a few major technical challenges have been overcome. Other than that, Py2neo 1.6 is the perfect companion to Neo4j 2.0 and well worth a try!

Py2neo 1.6 is available from PyPI, the source is hosted on GitHub and the documentation at ReadTheDocs. For a full list of changes, have a peek at the release notes.

/Nigel Small (@technige)

1 comment:

SethW from Firebox said...

Hi Nigel, Thanks for the introduction on Py2neo. I'm looking forward to use it.