NoSQL Zone is brought to you in partnership with:

Max De Marzi, is a seasoned web developer. He started building websites in 1996 and has worked with Ruby on Rails since 2006. The web forced Max to wear many hats and master a wide range of technologies. He can be a system admin, database developer, graphic designer, back-end engineer and data scientist in the course of one afternoon. Max is a graph database enthusiast. He built the Neography Ruby Gem, a rest api wrapper to the Neo4j Graph Database. He is addicted to learning new things, loves a challenge and finding pragmatic solutions. Max is very easy to work with, focuses under pressure and has the patience of a rock. Max is a DZone MVB and is not an employee of DZone and has posted 60 posts at DZone. You can read more from them at their website. View Full User Profile

Neo4j Spatial, Part 1: Building a Recommendation Engine

  • submit to reddit


It created 4 nodes for us. A special 0th node called “Spatial Root”, node 1 which we’ll take a look at in a second, and the root of an R-Tree and another node that holds the R-Tree Metadata. Let’s take a closer look at node 1:


Take a look at that name, “restaurants”… that’s right, we’re not using Lucene or some other kind of external index engine, we are building the index inside of our own graph! Alright, let’s add that restaurant.

node = @neo.create_node({:name => "Indie Cafe", :lat => 41.990326, :lon => -87.672907 })

It created node 4, not connected to anything else, just kind of hanging around…

Screen Shot 2014-01-31 at 7.28.27 PM

So let’s now add this node to our spatial index:

@neo.add_node_to_spatial_index("restaurants", node)

An additional node 5 was created, with an “id” property that points back to our restaurant “node 4″.

Screen Shot 2014-01-31 at 7.31.28 PM

To make sure this is working right, let’s try querying our index. We’ll execute a cypher query that looks to the node spatial index “restaurants” for anything that appears within 10.0 kilometers of latitude 41.99, longitude -87.67.

@neo.execute_query("start n = node:restaurants({location}) return n",
                   {:location => "withinDistance:[41.99,-87.67,10.0]"})

… and we find it:

...{"data"=>{"lon"=>-87.672907, "lat"=>41.990326, "name"=>"Indie Cafe"}...

Excellent, now let’s try adding a second restaurant.

node2 = @neo.create_node({:name => "La Ciudad", :lat => 41.964239, :lon => -87.654758 })
@neo.add_node_to_spatial_index("restaurants", node2)

Our R-Tree gets another branch, and our tree root properties change to encompass both branch nodes:

Screen Shot 2014-01-31 at 7.47.09 PM

We’ll query our graph one more time:

@neo.execute_query("start n = node:restaurants({location}) return n",
                   {:location => "withinDistance:[41.99,-87.67,10.0]"})

… and we see we get back both restaurants.

...{"data"=>{"lon"=>-87.672907, "lat"=>41.990326, "name"=>"Indie Cafe"}}...
...{"data"=>{"lon"=>-87.654758, "lat"=>41.964239, "name"=>"La Ciudad"}}...

So now you have a good handle on how the simplest part of the Neo4j Plugin works. On the next blog post, we’ll use what we have learned here to build the full application, and explore the more intricate parts of the Neo4j Spatial plugin in future blog posts.

Published at DZone with permission of Max De Marzi, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)