About Michael Hunger

Posts by Michael Hunger:

 
0

Neo4j 3.0 Stored Procedures

on Feb 29, 2016 in cypher, java

One of the many exciting features of Neo4j 3.0 are “Stored Procedures” that, unlike the existing Neo4j-Server extensions are directly callable from Cypher.

At the time of this writing it is only possible to call them in a stand-alone statement with CALL package.procedure(params)
but the plan is to make them a fully integrated part of Cypher statements.
Either by making CALL a clause or by turning procedures into function-expressions (which would be my personal favorite).

Currently procedures can only be written in Java (or other JVM languages).
You might say, “WTF …​ Java”, but it is less tedious than it sounds.

First of all, the effort of setting up a procedure project, writing and building it is minimal.

To get up and running you first need a recent copy of Neo4j 3.0,
either the 3.0.0-M04 milestone or the latest build from the Alpha Site.

To get you started you also need a JDK and a build tool like Gradle or Maven.

You can effectively copy the procedure template example that Jake Hansson provided in neo4j-examples as a starting point.

But let me quickly walk you through an even simpler example (GitHub Repository).

You need to declare the org.neo4j:neo4j:3.0.0[-M04] dependency in the provided scope, to get the necessary annotations and the Neo4j API to talk to the database.

pom.xml
<dependency>
  <groupId>org.neo4j</groupId>
  <artifactId>neo4j</artifactId>
  <version>${neo4j.version}</version>
  <scope>provided</scope>
</dependency>
build.gradle
project.ext {
    neo4j_version = ""
}
dependencies {
	compile group: "org.neo4j", name:"neo4j", version:project.neo4j_version
	testCompile group: "org.neo4j", name:"neo4j-kernel", version:project.neo4j_version, classifier:"tests"
	testCompile group: "org.neo4j", name:"neo4j-io", version:project.neo4j_version, classifier:"tests"
	testCompile group: "junit", name:"junit", version:4.12
}

If you have a great idea on what kind of procedure you want to write, just open a file with a new class.

Please note that the only package and method names become the procedure name (but not the class name).

In our example we will create a very simple procedure that just computes the minimum and maximum degrees of a certain label.

The reference to Neo4j’s GraphDatabaseService instance is injected into your class into the field annotated with @Context.
As procedures are meant to be stateless, declaring non-injected non-static fields is not allowed.

In our case the procedure will be named stats.degree and called like CALL stats.degree('User').

package stats;

public class GraphStatistics {

    @Context private GraphDatabaseService db;

    // Result class
    public static class Degree {
        public String label;
        // note, that "int" values are not supported
        public long count, max, min = Long.MAX_VALUE;

        // method to consume a degree and compute min, max, count
        private void add(long degree) {
          if (degree < min) min = degree;
          if (degree > max) max = degree;
          count ++;
        }
    }

    @Procedure
    public Stream<Degree> degree(String label) {
        // create holder class for results
        Degree degree = new Degree(label);
        // iterate over all nodes with label
        try (ResourceIterator it = db.findNodes(Label.label(label))) {
            while (it.hasNext()) {
               // submit degree to holder for consumption (i.e. max, min, count)
               degree.add(it.next().getDegree());
            }
        }
        // we only return a "Stream" of a single element in this case.
        return Stream.of(degree);
    }
}

If you want to test the procedures quickly without spinning up an in-process server and connecting to it remotely (e.g. via the new binary bolt protocol as shown in the procedure-template), then you can use the test-facilities of Neo4j’s Java API.

Now we can test our new and shiny procedure by writing a small unit-test.

package stats;

class GraphStatisticsTest {
    @Test public void testDegree() {
        // given Alice knowing Bob and Charlie and Dan knowing no-one
        db.execute("CREATE (alice:User)-[:KNOWS]->(bob:User),(alice)-[:KNOWS]->(charlie:User),(dan:User)").close();

        // when retrieving the degree of the User label
        Result res = db.execute("CALL stats.degree('User')");

        // then we expect one result-row with min-degree 0 and max-degree 2
        assertTrue(res.hasNext());
        Map<String,Object> row = res.next();
        assertEquals("User", row.get("label"));
        // Dan has no friends
        assertEquals(0, row.get("min"));
        // Alice knows 2 people
        assertEquals(2, row.get("max"));
        // We have 4 nodes in our graph
        assertEquals(4, row.get("count"));
        // only one result record was produced
        assertFalse(res.hasNext());
    }
}

Of course you can use procedures to create procedures, e.g. in other languages that are supported natively on the JVM like JavaScript via Nashorn, or Clojure, Groovy, Scala, Frege (Haskell), (J)Ruby or (J/P)ython.
I wrote one for creating and running procedures implemented in JavaScript.

There are many other cool things that you can do with procedures, see the resources below.

If you have ideas for procedures or wrote some of your own, please let us know.

Join our public Slack channel and visit #neo4j-procedures.

Resources

 
0

Using XRebel 2 with Neo4j

on May 5, 2015 in neo4j

At Spring.IO in Barcelona I met my pal Oleg from ZeroTurnaround and we looked at how the new XRebel 2
integrates with Neo4j, especially with the remote access using the transactional Cypher http-endpoint.

As you probably know, Neo4j currently offers a remoting API based on HTTP requests (a new binary protocol is in development).

Our JDBC driver utilizes [...]

 
0

Neo4j Server Extension for Single Page Experiments

on Apr 24, 2015 in neo4j, server

Sometimes you have a nice dataset in Neo4j and you’d want to provide a self-contained way of quickly exposing it to the outside world without a multi-tier setup.

So for experiments and proofs of concepts it would be helpful to be able to extend Neo4j Browser to accomodate new types of frames and commands.
Unfortunately we’re not [...]

 
0

How To: Neo4j Data Import – Minimal Example

on Apr 18, 2015 in import, neo4j

We want to import data into Neo4j, there are too many resources with a lot of information which makes it confusing.
Here is the minimal thing you need to know.

Imagine the data coming from the export of a relational or legacy system, just plain CSV files without headers (this time).

people.csv

1,”John”
10,”Jane”
234,”Fred”
4893,”Mark”
234943,”Anne”

friendships.csv

1,234
10,4893
234,1
4893,234943
234943,234
234943,1

Graph Model

Our graph Model would be very [...]

 
1

On Neo4j Indexes, Match & Merge

on Apr 11, 2015 in cypher, neo4j

We at Neo4j do our fair share to cause confusion of our users. I’m talking about indexes my friends.
My trusted colleagues Nigel Small – Index Confusion and Stefan Armbruster – Indexing an Overview already did a great job explaining the indexing situation in Neo4j,
I want to add a few more aspects here.

Since the release of [...]

 
5

Natural Language Analytics made simple and visual with Neo4j

on Jan 8, 2015 in cypher, fun

I was really impressed by this blog post on Summarizing Opinions with a Graph from Max and always waited for Part 2 to show up :)

The blog post explains an really interesting approach by Kavita Ganesan which uses a graph representation of sentences of review content to extract the most significant statements about a product.

Each [...]

 
2

Spring Data Neo4j 3.3.0 – Improving Remoting Performance

on Dec 9, 2014 in neo4j, spring-data-neo4j

With the first milestone of the Spring Data “Fowler” release train, Spring Data Neo4j 3.3.0.M1 was released. Besides a lot of smaller fixes, it contains one big improvement. I finally found some time to work on the remoting performance of the library, i.e. when used in conjunction with Neo4j Server. This blog post explains the [...]

 
0

The Story of GraphGen

on Nov 1, 2014 in community, development, neo4j

This is the story behind the really useful and ingenious Neo4j example graph data generator developed by Christophe Willemsen.

I don’t just want to show you the tool but also tell the story how it came to be.

First of all: The Neo4j Community is awesome.
There are so many enthusiastic and creative people, that it is often [...]

 
3

LOAD CSV with SUCCESS

on Oct 18, 2014 in cypher, import, neo4j

pre { word-wrap: normal; white-space:pre; overflow-x:scroll; }

I have to admit that using our LOAD CSV facility is trickier than you and I would expect.
Several people ran into issues that they could not solve on their own.

My first blog post on LOAD CSV is still valid in it own right, and contains important aspects that I [...]

 
5

Flexible Neo4j Batch Import with Groovy

on Oct 9, 2014 in import, neo4j

You might have data as CSV files to create nodes and relationships from in your Neo4j Graph Database.
It might be a lot of data, like many tens of million lines.
Too much for LOAD CSV to handle transactionally.

Usually you can just fire up my batch-importer and prepare node and relationship files that adhere to its input [...]

Copyright © 2007-2016 Better Software Development All rights reserved.
Multi v1.4.5 a child of the Desk Mess Mirrored v1.4.6 theme from BuyNowShop.com.