Over a million developers have joined DZone.

For Node.js and React.js Devs: A New Neo4j Movies Template

DZone's Guide to

For Node.js and React.js Devs: A New Neo4j Movies Template

In this post we take a look at how to make your first, complete demo application leveraging Neo4j and its demo movie dataset. Read on for the full story.

· Database Zone ·
Free Resource

Download the Scale-Out and High Availability whitepaper. Learn why leading enterprises choose the Couchbase NoSQL database over MongoDB™ after evaluating side by side.

Let’s jump right into it. You’re a JavaScript developer interested in Neo4j and want to build a web app, microservice or mobile app.

You’ve already read up on Neo4j, played around with some datasets, and know enough Cypher to get going. Now you’re looking for a demo app or template to get the ball rolling – you’ve come to the right place.

Enter the Neo4j Movies Template

What comes with the Neo4j Movies Template:

The Movie Demo Application

The Model: This project uses a classic Neo4j dataset: the movie database. It includes Movie, Person, Genre and Keyword nodes, connected by relationships as described in the following image:
Learn all about how to use Node.js and React.js with Neo4j with this new Movies template

The API: The Node.js portion of the application interfaces with the database and presents data to the React.js front-end via a RESTful API.

The front-end: The front-end, in this case is built in React.js, consumes the data presented by the Express.js API and presents some views to the user, including the home page, a Movie detail page and a Person detail page.

Setting Up

To get the project running, clone the repo then check the project’s README for environment-specific setup instructions.

Use neo4j-import to Import CSV Files into the Database

In this example app, every node type and relationship type has its own CSV file. In order to create and view the movie graph:
  • Download and install Neo4j
  • Import the nodes
  • Import the relationships
  • Start the database!
If you’re on Unix and downloaded the .tar version of Neo4j you should be fine using stock neo4j-import.

If you’re on Mac or Windows and downloaded the .dmg or .exe versions of Neo4j, try replacing the $NEO4J_HOME/bin/neo4j-import part of the import script with the appropriate replacement. For example, this would be the alternate command for Windows on Neo4j 3.0.3:

"C:\Program Files\Neo4j Community\jre\bin\java" -cp "C:\Program Files\Neo4j
Community\bin\neo4j-desktop-3.0.3.jar" org.neo4j.tooling.ImportTool --into database/ 
--nodes:Person csv/person_node.csv --nodes:Movie csv/movie_node.csv --nodes:Genre
csv/genre_node.csv --nodes:Keyword csv/keyword_node.csv --relationships:ACTED_IN
csv/acted_in_rels.csv --relationships:DIRECTED csv/directed_rels.csv 
--relationships:HAS_GENRE csv/has_genre_rels.csv --relationships:HAS_KEYWORD csv/has_keyword_rels.csv --relationships:PRODUCED csv/produced_rels.csv 
--relationships:WRITER_OF csv/writer_of_rels.csv --delimiter ";" --array-delimiter "|" 
--id-type INTEGER

Start the Node.js Backend

The Neo4j-powered Express.js API lives in the api directory. 
The Neo4j and Express.js API

In order to run the API, you’ll need to open a new terminal tab and move to the api directory install dependencies using npm install:

cd api
npm install

If your terminal does not know the command npm, make sure you have installed Node.js, perhaps choosing nvm to manage your version of Node.js (I’m using v6.2.1). 

After you’ve installed your dependencies and have your database running, start the API using:

node app.js

Over on the API’s documentation page, http://localhost:3000/docs/, select on /genres and then press the Try it out! button to see a sample API call. 
The Node.js and Neo4j API documentation

If you run into problems, make sure your database is actually running and that you’ve entered your database credentials in the api/config.js file.

The Config.js API

Start the React.js Front-End

The React.js front-end

With the database and Express.js backend running, open a new terminal tab or window and move to the project’s /web subdirectory. Install the bower and npm dependencies, then start the app by running gulp (read the “getting started” on gulpjs.com if this is your first time using gulp).

npm install
bower install

Over on http://localhost:4000/, you should see the homepage of the movie app, displaying three featured movies and some members of the Action genre. 
A Neo4j and JavaScript movies web app

Click on a movie to see the movie detail page:

A sample movie app using JavaScript and Neo4j

Click on a person to see that person’s related persons and movies the person has acted in, directed, written or produced:

An Andy Wachowski example in a Neo4j and JavaScript sample movies app

A Closer Look

Using the JavaScript Neo4j Bolt Driver

Let’s take a closer look at what sort of responses we get from the JavaScript Bolt driver. In this app, calls to the database are handled by /api/neo4j/dbUtils.js, described piece by piece below. 

Import dependencies, including the Neo4j driver and connecting the driver to the database:

var nconf = require('../config');

var neo4j = require('neo4j-driver').v1;
var driver = neo4j.driver(nconf.get('neo4j-local'), neo4j.auth.basic(nconf.get('USERNAME'), nconf.get('PASSWORD')));

Let’s look at how we would ask the database to return all the genres in the database. getAll (below) submits a Cypher query and passes the result from the database through the _manyGenres function, which maps the results into a usable form and deals with converting Neo4j integers to JavaScript numbers. 

var _ = require('lodash');
var Genre = require('../models/neo4j/genre');

var getAll = function(session) {
  return session.run('MATCH (genre:Genre) RETURN genre')

var _manyGenres = function (result) {
  return result.records.map(r => new Genre(r.get('genre')));

module.exports = {
  getAll: getAll

// extracts just the data from the query results

var _ = require('lodash');

var Genre = module.exports = function (_node) {
  _.extend(this, _node.properties);
  if (this.id) { 
    this.id = this.id.toNumber();

The query going in: 
MATCH (genre:Genre) RETURN genre

Completely unprocessed records coming out: 
{ records:
   Record {
  keys: [ 'genre' ],
  length: 1,
  _fields: [ Node {
    identity: Integer { low: 737, high: 0 },
   labels: [ 'Genre' ],
   properties: { name: 'Suspense', id: Integer { low: 3270, high: 0 } } ],
  _fieldLookup: { genre: 0 } },

      ... // more records
   ResultSummary {
     statement: { text: 'MATCH (genre:Genre)\nRETURN genre', parameters: {} },
     statementType: 'r',
     updateStatistics: StatementStatistics { _stats: [Object] },
     plan: false,
     profile: false,
     notifications: [] } }

In order to grab the genre node, we would use record.get('genre') to get the following data: 
Node {
  identity: Integer { low: 735, high: 0 },
  labels: [ 'Genre' ],
  properties: { name: 'Family', id: Integer { low: 1258, high: 0 } } }

This is better, but still not usable. We want to feed results like the following into an array to present to the frontend. 
    "name": "Family",
    "id": 1258

The return function parses the messy results into the data we need: 
var _manyGenres = function (result) {
  return result.records.map(r => new Genre(r.get('genre')));

Voila! An array of genres appears at /genres

Beyond the /Genres Endpoint

Of course, an app that just shows movie genres isn’t very interesting. Take a look at the routes and models used to build the home page, movie detail page and person detail page. 

Next Steps

  • Fork the repo and hack away! Find directors that work with multiple genres, or find people who happen to work with each other often as writer-director pairs.
  • Find a way to improve the template or the JS driver? Make a GitHub Issue and/or submit a pull request.

Learn how to scale enterprise applications easily, efficiently, and reliably with NoSQL. See why Couchbase beats MongoDB™ for scale-out and high availability.

neo4j ,node.js ,react.js ,database

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}