Thursday, April 1st, 2010

Basic Neo4j through Groovy

Neo4j is a graph database, recently released in a 1.0 version (see the Neo4j site). The main programming interface is Java. A lot of Java stuff looks much groovier when run from Groovy. Why not give Neo4j a try?

This post takes the little "Hello world" program from the Neo4j Getting Started Guide and makes it somewhat groovier. A later post will demonstrate a more complete program.

I downloaded the Neo4j 1.0 distribution and collected the jars in /jlib to keep the class path short. I also created an empty directory in /sdb3/cur/data/neo1 to hold my first database. Change these paths to suit your taste and environment.

Our first Groovy script hello1.groovy starts the database, begins a transaction, does nothing and then closes.

GROOVY:
  1. import org.neo4j.kernel.*
  2. import org.neo4j.graphdb.*
  3.  
  4. db = new EmbeddedGraphDatabase("/sdb3/cur/data/neo1")
  5. tx = db.beginTx()
  6. tx.success()
  7. tx.finish()
  8. db.shutdown()

Run the script like this from a command line. This is Unix style. If you run under Windows you must change the colons into semicolons in the class path.

groovy -classpath /jlib/neo4j.jar:/jlib/jta.jar hello1.groovy

No errors, no nothing. How can I know it ran at all? Have a look in the database directory and you will find quite a number of files representing Neo4j nothingness. (Actually a reference node is always created.)

On the logical level a Neo4j database consists of nodes and relationships between nodes. A node may have any number of name/value pairs called properties. A relationship may also have any number of properties. The Java API provides getProperty and setProperty methods for getting and setting properties. These are very common operations that deserve a better syntax. Add the following Groovy metaclass magic to the script.

GROOVY:
  1. ExpandoMetaClass.enableGlobally()
  2. PropertyContainer.metaClass.getProperty = {name -> delegate.getProperty(name)}
  3. PropertyContainer.metaClass.setProperty = {name, val -> delegate.setProperty(name, val)}

Now properties may be accessed using dot notation. The magic is applied to PropertyContainer to make it work for nodes as well as relationships.

The next version of the script, hello2.groovy, creates two nodes, a relationship between them as the original Hello World example does. It also adds a property named message to the nodes as well as the relationship.

GROOVY:
  1. import org.neo4j.kernel.*
  2. import org.neo4j.graphdb.*
  3.  
  4. ExpandoMetaClass.enableGlobally()
  5. PropertyContainer.metaClass.getProperty = {name -> delegate.getProperty(name)}
  6. PropertyContainer.metaClass.setProperty = {name, val -> delegate.setProperty(name, val)}
  7.  
  8. db = new EmbeddedGraphDatabase("/sdb3/cur/data/neo1")
  9. tx = db.beginTx()
  10. DOIT()
  11. tx.success()
  12. tx.finish()
  13. db.shutdown()
  14.  
  15. def DOIT() {
  16.     def node1 = db.createNode()
  17.     node1.message = 'Hello'
  18.     def node2 = db.createNode()
  19.     node2.message = 'world!'
  20.     def knows = DynamicRelationshipType.withName("KNOWS")
  21.     def rel = node1.createRelationshipTo(node2, knows)
  22.     rel.message = 'brave Neo4j'
  23.     println "${node1.message} ${rel.message} ${node2.message}"
  24. }

I refactored the core logic into a separate method DOIT in order to separate it from the scaffolding. The script ends by printing the message properties of the new nodes and relationship. This version is very similar to the original Hello World. Try it from the command line like the previous version.

The script supposedly adds two new nodes and a relationship to the database every time you run the script, but how can we tell? Let's replace the DOIT method to print out all nodes currently the database.

The metaclass magic with dot notation has its limits. I had to introduce an extra metaclass method and use square brackets to access properties.

GROOVY:
  1. PropertyContainer.metaClass.getAt = {idx -> delegate.getProperty(name)}
  2.  
  3. def DOIT() {
  4.     db.allNodes.each {node ->
  5.         println "${node}:"
  6.         node.getPropertyKeys().each {key ->
  7.             println "  ${key} = ${node[key]}"
  8.         }
  9.         node.getRelationships().each {rel ->
  10.             println "  has rel ${rel.getType().name()}"
  11.         }
  12.     }
  13. }

The script now prints all nodes in the database. For every node it prints all properties and also relationship names. This is a bonus compared to the original example.

To be really useful any Neo4j program needs decent exception handling. Our script also mimics the original Hello World by creating objects attached to nothing. A real Neo4j application needs some kind of entry point into the graph of nodes. All this is remedied in the next example.

6 Comments on “Basic Neo4j through Groovy”


  1. Coolio! Btw, one way to check what’s in the database is to fire up the Neo4j shell:

    http://wiki.neo4j.org/content/Shell_Matrix_Example

    -EE


  2. Of course, I should also mention that the shell supports running Groovy scripts:

    http://wiki.neo4j.org/content/Shell#Executing_groovy.2Fpython_scripts

    -EE


  3. [...] This post was mentioned on Twitter by Emil Eifrem, Jeppe Cramon. Jeppe Cramon said: Basic Neo4j through Groovy. It seems to be 1st in a series about #neo4j and #groovy. http://www.soderstrom.se/?p=81 #nosql (via @emileifrem) [...]

  4. Stefan

    You might use @Grab in your Groovy code to directly include the dependency to the Neo4j jars. When doing this, you no longer need to struggle with your classpath.


  5. Social comments and analytics for this post…

    This post was mentioned on Twitter by emileifrem: “Basic Neo4j through Groovy.” It seems to be 1st in a series about #neo4j and #groovy. http://www.soderstrom.se/?p=81 #nosql…

  6. Håkan

    Good stuff above finally dug out from russian spam.

Leave a Reply

You must be logged in to post a comment.