Find Van Gogh’s artworks next to you, with Neo4j Spatial and Spring Data Neo4j 3.0.1

1. Introduction


In March, Michael Hunger (Head of Spring Integration) and Spring Data team officially released Spring Data Neo4j 3.0.1. As an useful intro, I kindly suggest you to watch the video posted  here.

Since, my company and me have for many years adopted the Spring Framework to develop our web applications, it was natural for me to start a new spike, whose main objective was to use a geographical search engine to look for museums hosting masterpieces by Van Gogh next to my friends and me.

I rapidly understood that my technical stack could have been built by:


  • Neo4j Spatial, a library for Neo4j that helps to execute spatial operation on data;



  • Heroku: as environment where to deploy this spike.


You can watch full code on my public github project (contributors welcome);

Application is reachable at:

2. Configuration of Spring Data Neo4j 3.0.1


Configuring SDN is quite easy:

Last one is therefore specific for SDN and we can use an XML namespace to configure Spring Data Neo4j:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns=""

The <neo4j:config> element provides an XML-based configuration of Spring Data Neo4j in one line. For convenience, storeDirectory can be set to point to a directory where our EmbeddedGraphDatabase resides (we could have defined a GraphDatabaseService as well):

<neo4j:config base-package="it.inserpio.neo4art.domain" storeDirectory="data/graph.db" />

Then we enabled repository support in the Spring context configuration by simply adding:

<neo4j:repositories base-package="it.inserpio.neo4art.repository"/>

I will talk about repository more in depth shortly (see chapter 4).

3. Object Graph Mapping


If we have decided to adopt SDN, then we have a third interesting alternative to (1) Java Neo4j core API and (2) Neo4J REST API to interact with our database: OGM, a simple direct POJO-mapping that automatically copy the data out of the graph,  into our entities.

Next picture summarises my domain model:


that can be mapped to my entity object as follow:

We can try to comment out this abstract of Museum class:

public class Museum extends AbstractEntity
  public static final String LOCATED_IN = "LOCATED_IN";
  public static final String OFFICIAL_LOCATION = "OFFICIAL_LOCATION";

  private String name;

  private String address;
  private String director;
  private String wikipedia;
  private String website;
  private Double latitude;
  private Double longitude;

  @Indexed(indexName="museumLocation", indexType=IndexType.POINT)
  private String wkt;

  @RelatedTo(type = OFFICIAL_LOCATION, direction = Direction.INCOMING, elementClass = Artwork.class)
  private Set<Artwork> artworks;

  [... setter / getter omitted ]

As we can see, there are four interesting annotation:

  • @NodeEntity: used to identify entity classes;
  • @TypeAlias: used to create labels on nodes;
  • @Indexed:  used to create indexes. Museum class comes with two indexes: (1) an unique index on name field and (2) a spatial index, called musuemLocation on wkt field;
  • @RelatedTo: used to find connected entities. For Museum class, artworks field will be populated with all artworks officially located (:OFFICIAL_LOCATION) in this museum.

Repositories will automatically copy query results into these object!

4. Repository


Spring Data Commons repository infrastructure is also available in Spring Data Neo4j. Repositories consist only of interfaces that specify available functionality, while implementation details of commonly used persistence methods are handled by the library. This is particularly valid for CRUD, index- and query-operations.

As we can see in the following abstract of MuseumRepository class, repositories are extensible by annotated, named or derived finder methods (of course, we are free to implement our own code too).

All we have to do is to declare our interface extends GraphRepository interface:

public interface MuseumRepository extends GraphRepository<Museum>, SpatialRepository<Museum>
         "WHERE id(a)={artistId} " +
         "RETURN distinct(m) as museums")
  List<Museum> findMuseumByArtist(@Param("artistId") long artistId);

And to take advantage of the following spatial searches we need to extend SpatialRepository interface too:

EndResult<T> findWithinBoundingBox(String indexName, double lowerLeftLat, double lowerLeftLon,
                                                     double upperRightLat, double upperRightLon);

EndResult<T> findWithinDistance( final String indexName, final double lat, double lon, double distanceKm);

EndResult<T> findWithinWellKnownText( final String indexName, String wellKnownText);

For deeper knowledge you can see “20.11 Geospatial Queries“.

5. Testing “Van Gogh Radar”


As previoulsy said, you can access Van Gogh Radar at:

Application requires if you would like to share your location, so that the map will be centered according to your coordinates – otherwise the map will be initialized to Venice 😉

You can search by inserting longitude and latitude you are interested in. As an example you could try with Amsterdam (log: 52.366667, lat: 4.9) and search for museum within distance 100Km:



or you can try with Neo4j office location. For example if you choose Neo4j London office we have:



Then you can get information about the museum you are interested in by rolling over his icon:



To retrieve the list of Van Gogh’s artworks hosted by the museum you selected, click on “SHOW HOSTED PAINTINGS”:



And finally you can see a preview of every painting:



Now you have no excuses: thanks to Neo4j Spatial Searches, you cannot miss even one of Van Gogh’s artworks anymore! 🙂



4 thoughts on “Find Van Gogh’s artworks next to you, with Neo4j Spatial and Spring Data Neo4j 3.0.1

  1. Pingback: Extending the Neo4j Server with Spring Data Neo4j | Lorenzo Speranzoni's Blog

  2. Pingback: Neo4Art moves to Cloud Foundry at SpringOne 2GX 2014 | Lorenzo Speranzoni's Blog

  3. Pingback: Neo4j at SpringOne 2GX 2014 - Neo4j Graph Database

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s