This Neo4j-based node / react web app displays movie and person data in a manner similar to IMDB. It is designed to serve as a template for further development projects. Feel encouraged to fork and update this repo!
Movie
Person
Genre
Keyword
(:Person)-[:ACTED_IN {role:"some role"}]->(:Movie)
(:Person)-[:DIRECTED]->(:Movie)
(:Person)-[:WRITER_OF]->(:Movie)
(:Person)-[:PRODUCED]->(:Movie)
(:MOVIE)-[:HAS_GENRE]->(:Genre)
Unix Video Instructions
- Download Neo4j Community Edition: .tar Version
- video instructions start here
- Set your
NEO4J_HOME
variable: `export NEO4J_HOME=/path/to/neo4j-community - From this project's root directory, run the import script:
$NEO4J_HOME/bin/neo4j-import --into $NEO4J_HOME/data/databases/graph.db --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
If you see Input error: Directory 'neo4j-community-3.0.3/data/databases/graph.db' already contains a database
, delete the graph.db
directory and try again.
- Start the database:
$NEO4J_HOME/bin/neo4j console
- Add constraints to your database:
$NEO4J_HOME/bin/neo4j-shell < setup.cql
Download Neo4j Community Edition
neo4j-import
does not come with Neo4j-Desktop (.exe
on Windows, .dmg
on OSX).
To get around this issue, find your OS here and try using the alternate import command for your system.
Update the Neo4j version in the snippet with whatever you're using, and replacing "$@"
or %\*
with:
--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
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
Use the GUI to select and start your database.
- Start Neo4j if you haven't already!
- Set your username and password
- You should see a database populated with
Movie
,Genre
,Keyword
, andPerson
nodes.
From the root directory of this project:
cd api
npm install
- in
config.js
, update the credentials for your database as needed node app.js
starts the API- Take a look at the docs at http://localhost:3000/docs
From the root directory of this project:
cd flask-api
pip install -r requirements.txt
(you should be using a virtualenv)- set your neo4j database username
export MOVIE_DATABASE_USERNAME=myusername
- set your neo4j database password
export MOVIE_DATABASE_PASSWORD=mypassword
export FLASK_APP=app.py
flask run
starts the API- Take a look at the docs at http://localhost:5000/docs
From the root directory of this project, set up and start the frontend with:
cd web
npm install
(ifpackage.json
changed)bower install
to install the styles- update config.settings.js file
** if you are using the Node API:
cp config/settings.example.js config/settings.js
** if you are using the flask api then editconfig/settings.js
and change theapiBaseURL
tohttp://localhost:5000/api/v0
gulp
starts the app on http://localhost:4000/
If you're running the app locally, you might want to tweak or explore ratings without having a robust community of users.
In the /csv
directory, note that there is a file called ratings.csv
.
This file contains some pseudo-randomly generated users and ratings.
Load the users and ratings:
Move ratings.csv
into the import
directory of your database either by dragging and dropping or using
cp csv/ratings.csv $NEO4J_HOME/import/ratings.csv
![put ratings.csv into the import directory](./img/ratings_csv.png =250x)
Assuming your database is running, paste the following query into the Neo4j browser:
LOAD CSV WITH HEADERS FROM 'file:///ratings.csv' AS line
MATCH (m:Movie {id:toInt(line.movie_id)})
MERGE (u:User {id:line.user_id, username:line.user_username}) // user ids are strings
MERGE (u)-[r:RATED]->(m)
SET r.rating = toInt(line.rating)
RETURN m.title, r.rating, u.username
If you don't want to use the browser, you can uncomment out the above query in setup.cql
and run it again using $NEO4J_HOME/bin/neo4j-shell < setup.cql
Based on my similarity to other users, user Sherman
might be interested in movies rated highly by users with similar ratings as himself.
MATCH (me:User {username:'Sherman'})-[my:RATED]->(m:Movie)
MATCH (other:User)-[their:RATED]->(m)
WHERE me <> other
AND abs(my.rating - their.rating) < 2
WITH other,m
MATCH (other)-[otherRating:RATED]->(movie:Movie)
WHERE movie <> m
WITH avg(otherRating.rating) AS avgRating, movie
RETURN movie
ORDER BY avgRating desc
LIMIT 25
Site visitors interested in movies like Elysium
will likely be interested in movies with similar keywords.
MATCH (m:Movie {title:'Elysium'})
MATCH (m)-[:HAS_KEYWORD]->(k:Keyword)
MATCH (movie:Movie)-[r:HAS_KEYWORD]->(k)
WHERE m <> movie
WITH movie, count(DISTINCT r) AS commonKeywords
RETURN movie
ORDER BY commonKeywords DESC
LIMIT 25
Sherman
has seen many movies, and is looking for movies similar to the ones he has already watched.
MATCH (u:User {username:'Sherman'})-[:RATED]->(m:Movie)
MATCH (m)-[:HAS_KEYWORD]->(k:Keyword)
MATCH (movie:Movie)-[r:HAS_KEYWORD]->(k)
WHERE m <> movie
WITH movie, count(DISTINCT r) AS commonKeywords
RETURN movie
ORDER BY commonKeywords DESC
LIMIT 25
The Express API is located in the /api
folder.
The API itself is created using the Express web framework for Node.js. The API endpoints are documented using swagger and swagger-jsdoc module.
To add a new API endpoint there are 3 steps:
- Create a new route method in
/api/routes
directory - Describe the method with swagger specification inside a JSDoc comment to make it visible in swagger
- Add the new route method to the list of route methods in
/api/app.js
.
The flask API is located in the flask-api folder. The application code is in the app.py
file.
The API itself is created using the Flask-RESTful library. The API endpoints are documented using swagger with the flask-restful-swagger-2 library.
To add a new API endpoint there are 3 steps:
- Create a new Flask-RESTful resource class
- Create an endpoint method including the swagger docs decorator.
- Add the new resource to the API at the bottom of the file.