Embracing Reality with Neo4j

-- Life is a Graph and Neo4j is Epic --

Introductions to Neo4j What is NoSQL Asia? Help Organize NoSQL Asia NoSQL Asia News


It's deep - but the truth often it.

Reality is a graph - embrace it!

This is their tagline and often found on t-shirts and mugs that at the moment, I unfortunately do not own.

It also has a whole lot of un-expected truth to it, but it is this golden nugget that really sparked my interest:

In a properly mapped Neo4j graph, the size of your data does not effect the speed of an appropriately relational query.

However, Neo4j and the concept of graphs is not a topic for the faint of heart, and to be honest, I have absolutely no idea why I find myself (as a web-designer by trade) being drawn to it without reason. It's truly madness, or is it...?

It's true - I've gone a bit nuts over NoSQL of late, but with good reason, for we have now defined the position of DevOps - something I have zero interest in. With this new generation of data-storage platforms, we have finally empowered designers and developers to take a more active role in a larger stack. Despite this, and whilst ignoring my dislike for setting-up new toys, I finally managed to find a weekend in which I could play with Neo4j. My first and most simplified impression; this thing is epic.


The Administration Console


This database was clearly not "designed" for people such as me, who prefer to use GUIs over console, and yet ironically, it is the first database that I have used that has it's own built in GUI. Strange but true. It needs a lot of work, but can nonetheless find no true faults and proves to be very useful for first-timers, especially when it comes with built-in documentation too!

Not to mention gremlins and real moving graphs! :-)

But seriously, when I said this thing was epic, it was for a reason.


Neo4j Features


People familiar with console and Linux commands such as cd and ls whilst prefixing things like ls -p should feel right at home!

At it's core, it could be seen as nothing more than a large file system, and you are free to traverse that system by using console commands. It achieves ACID compliance by utilizing its own internal transactional repository system where full audit trails and instant rollback are said to be easily available.

Not only does it come with an administration panel (as mentioned above) that includes general statics and server performance on the dashboard, but you can also browser your data through a visual representation of the graph itself. If you do not have access to a console, no worries, the admin panel has one built in, which not only simulates interaction with its built-in REST API but can also accept Gremlin commands and queries along with Neo4j's own console language and querying syntax.

Did I already mention this thing was epic?


Graph Databases


For those that have yet to try Neo4j, it is worth noting (as noted by countless others) that you need to be a fan of Sci-Fi to appreciate the demos and data-sets - as this great illustration of a really basic graph shows:


Relationships on Steroids


As shown in the visual above, each node and relationship can hold any properties provided, like mini-documents of their own, but it's when you start to understand the the context of the relationships themselves, acting like persistent joins that things get interesting...

This allows for rapid retrieval of data from connected nodes and facilitates accurate recommendation services.

Words speak a thousands words

Corey Farwell created this controversial visualization:

...but if you want the technicalities behind Neo4j and graphs, InfoQ would probably be the place to be.

A quick look at Cypher (the native Neo4j query language) looks like (graphs)-[:relate]->(data), and to be honest, I am not a fan.

Nonetheless, we will get into some working examples later after we've taken a closer look behind the scenes at Neo4j.


NeoTechnology


NeoTechnology is the company behind Neo4j.

They started working on Neo4j in 2007 with version 1.0 pubnlic release reaching the market in 2010.

Their client list contains names such as Adobe, Cisco and Mozilla.

Here's a great non-technical introduction to graph databases and Neo4j by Andreas Kollegger:

Or for a more technical introduction from the creator himself, check-out Emil Eifrem's video:


Using Neo4j with HTML and jQuery


Since Neo4j features a solid HTTP REST API, I wanted to play around with HTML and jQuery.

Relationships aside for now, let's just look at plonking data into nodes (like we can with mongoDB). Obviously, Neo4j can only store JSON (less data types than BSON), so to put and get data to and from Neo4j with a simple form, we could use something similar to:

<!doctype html>
<html>
<head>

<meta charset='utf-8' />
<title>GraphVerse</title>

<script>
var gp_options = new Array();
gp_options[''] = '';
</script>

<script id='js-jquery' src='js/jquery.js'></script>
<script id='js-graphverse' src='js/graphverse.js'></script>

</head>

<body>

	<form class="graphverse" data-action="put">
		<h3>Add node to graph:</h3>
		<input type="text" placeholder="name" name="name" class="graph-text" />
		<input type="submit" value="add" />
	</form>

	<form class="graphverse" data-action="get">
		<h3>Get node from graph:</h3>
		<input type="text" placeholder="node" class="graph-node" /><br />
		<input type="text" placeholder="data type" class="graph-data" />
		<input type="submit" value="get" />
	</form>

</body>

<script>

$(document).ready(function(e){
	$('body').GraphVerse();
})

</script>

</html>

Where GraphVerse would use:

/**
 * GraphVerse by Mark Smalley :: http://twitter.com/m_smalley
 * GitHub Repo :: https://github.com/msmalley/GraphVerse
 * License :: MIT
 */

;(function ( $, window, document, undefined )
{
	// Create the defaults once
	var pluginName = "GraphVerse",
        defaults = {
            node: 0
        };

    // The actual plugin constructor
	function Plugin( element, options ) {
        this.element = element;

        // jQuery has an extend method which merges the contents of two or
        // more objects, storing the result in the first object. The first object
        // is generally empty as we don't want to alter the default options for
        // future instances of the plugin
        this.options = $.extend( {}, defaults, options );

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

	Plugin.prototype = {

        init: function() {

            // Example = this.connect(this.element, this.options)

			var default_callback = this.callback;
			var put_contents = this.put;
			var get_contents = this.get;

			$('form.graphverse').each(function(i){
				$(this).on('submit', function(e){

					$this = $(this);

					action = $($this).attr('data-action');
					callback = $($this).attr('data-callback');

					if(!action) action = 'get';
					if(!callback) callback = default_callback;

					e.preventDefault();
					if(action == 'put')
					{
						var data = new Object();
						$($this).find('input.graph-text').each(function(i){
							data[$(this).attr('name')] = $(this).val();
						});
						put_contents(data, callback);
					}
					else if(action == 'get')
					{
						var node = $($this).find('input.graph-node').val()
						data = $($this).find('input.graph-data').val()
						get_contents(node, data, callback);
					}
				})
			});

        },

        get: function(node, data, callback) {
            // some logic
			var base_uri = 'http://localhost:7474';
			$.ajax({
				url: base_uri + '/db/data/node/' + parseInt(node) + '/',
				dataType: 'JSON',
				type: 'GET',
				success: function(results)
				{
					if(typeof window[callback] == 'function')
					{
						window[callback](results['data'][data]);
					}
					else
					{
						callback(results['data'][data]);
					}
				}
			})
        },

		put: function(data, callback) {
			var base_uri = 'http://localhost:7474';
			$.ajax({
				url: base_uri + '/db/data/node',
				dataType: 'JSON',
				type: 'POST',
				data: data,
				success: function(results)
				{
					if(typeof window[callback] == 'function')
					{
						window[callback](results['data']);
					}
					else
					{
						callback(results['data']);
					}
				}
			})
        },

		callback: function(results)
		{
			console.log(results);
		}
    };

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName, new Plugin( this, options ));
            }
        });
    };
})( jQuery, window, document );

I know it's hardly rocket-science, but had to start somewhere...

Am hoping to convince my boss to start using Neo4j in a project we are working-on, in which case, I'll be exploring things very deeply very soon, else my explorations with this fascinating new technology will need to wait until serendipity allows.

To be continued!


What is NoSQL Asia? Help Organize NoSQL Asia NoSQL Asia News




Written by Mark Smalley | Published on March 4th, 2013 Tags : neo4j graphs