Over a million developers have joined DZone.
Platinum Partner

Graph Visualization and Neo4j

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

So far we’ve learned how to get Neo4j up and running with Neography, how to find friends of friends and degrees of separation with the Neo4j REST API and a little bit of the Gremlin and Cypher languages. However, all we’ve seen is text output. We haven’t really “seen” a graph yet, but that’s about to change.

Vouched holds a graph of skill specific recommendations people have made to each other and visualizes it. I extracted the visualization, and hosted it on github as neovigator. You can get your very own visualization up and running or take a look at this instance running on Heroku.

Let’s get it up and running and then we’ll go through some pieces of the code.

git clone git@github.com:maxdemarzi/neovigator.git
cd neovigator
bundle install
rake neo4j:install
rake neo4j:start

Then visit localhost:9292 to see it running.

The website is a Sinatra Application with only two routes. The home page, and a resources route that returns a JSON object of one node and all his “next node neighbours”.

The JSON object we create will have this structure:

{"details_html":"Information which replaces the side panel",
         "id":"the id of the current node",
         "name":"the name of the current node",
         "attributes":[{"id":"id of 1st relationship type",
                        "name":"name of 1st relationship type",
                        "values":[{"id":"the id of our 1st neighbour",
                                   "name":"the name of our 1st neighbour"},
                                  {"id":"the id of our 2nd neighbour",
                                   "name":"the name of our 2nd neighbour"}]},
                       {"id":"id of 2nd relationship type",
                        "name":"name of 2nd relationship type",
                        "values":[{"id":"the id of our 3rd neighbour",
                                   "name":"the name of our 3rd neighbour"},
                                  {"id":"the id of our 4th neighbour",
                                   "name":"the name of our 4th neighbour"}]}]

When we fill this JSON object and pass it to the visualization, this is what we get:

We create a route in Sinatra and set it to return JSON.

get '/resources/show' do
  content_type :json

From our starting node, we are going to traverse the graph to a depth of 1, and get everything but our starting node.

neighbours =
  {"order"         => "depth first",
   "uniqueness"    => "none",
   "return filter" => {"language" => "builtin", "name" => "all_but_start_node"},
   "depth"         => 1}

Then we get our node and traverse the graph using the “fullpath” option which gives us the nodes and relationships.

node = neo.get_node(params[:id])
connections = neo.traverse(node, "fullpath", neighbours)

We are going to split up our incoming and outgoing relationships and get the ids of the “other node” so we can link to it.

incoming = Hash.new{|h, k| h[k] = []}
outgoing = Hash.new{|h, k| h[k] = []}

connections.each do |c|
   c["nodes"].each do |n|
     nodes[n["self"]] = n["data"]
   rel = c["relationships"][0]

   if rel["end"] == node["self"]
     incoming["Incoming:#{rel["type"]}"] << {:values => nodes[rel["start"]].
                                                        merge({:id => node_id(rel["start"]) }) 
     outgoing["Outgoing:#{rel["type"]}"] << {:values => nodes[rel["end"]].
                                                        merge({:id => node_id(rel["end"]) }) 

We then merge them together to create our neighbours array and put them in the attributes piece of our JSON object.

incoming.merge(outgoing).each_pair do |key, value|
  attributes << {:id => key.split(':').last, 
                 :name => key, 
                 :values => value.collect{|v| v[:values]} 

We then load our JSON object with a few more details, like the node id, name, and some of its properties.

{:details_html => "<h2>Neo ID: #{node_id(node)}</h2>#{get_properties(node)}",
 :data => {:attributes => attributes,
           :name => node["data"]["name"],
           :id => node_id(node)}

I will go over more details of how the visualization was done at FOSDEM 2012 in the Graph Processing Room on February 5th, 2012 at at 3:20 PM in the AW building room 1.125.

Processing is an open source programming language and environment for people who want to create images, animations, and interactions. Processing.js takes processing to the browser. It is written in JavaScript and uses HTML5′s canvas element. Michael Aufreiter adapted a motion tweening library for use with processing.js and built a radial navigator (Donut) for the project ASKKEN. Michael has given permission to use Donut as you’d like, checkout his amazing work with Substance.

Source:  http://maxdemarzi.com/2012/01/11/graph-visualization-and-neo4j/

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}