Building an app to help me decide what movie to watch next.

I wrote this blog post 4 years ago but never got a chance to publish it. I decided to publish it now because of my love for data visualization and movies.

The problem

I have a very large movie collection and most of the time I find it is very difficult to find a movie a watch, mainly because of the sheer size of my collection. This is a common problem in today’s society. Netflix tried to solve this problem by recommending movies you have not seen based on your taste. My approach is different. I decided to take a data-driven approach to this problem. Instead of writing an algorithm that suggests a movie to you, I decided to visually graph my movie library and discover movies I want to watch.

Solution

I decided to use D3.js (a data-driven library) to help me visualize my movie collection.

I decided on choosing two key features, runtime(X-axis) and IMBD Rating(Y-axis), for each movie

Since time is a strong factor for movie selection as well as quality, I would be able to identify quickly the best movie to fit my time criteria.

Implementation

For my application to work I need to query a database that has existing movies. For this application, I used OMDB API, which I query from my application and save the results on my own API client.

My API client provides three endpoints:

(GET): /api/films/
(POST): /api/films/
(DELETE): /api/films/:id

And saves the data in a non-relationship database, in this case, MongoDB.

Since non-relationship databases are schema-less, I am using Mongoose to help me with validation and typecasting. Below is an example of the schema for my movie collection:

var filmSchema = new mongoose.Schema({  
title: String,
year: Number,
rated: String,
released: Date,
runtime: Number,
genre: Array,
director: String,
writer: Array,
actors: Array,
plot: String,
language: Array,
country: String,
awards: String,
poster: String,
metascore: Number,
imdbRating: Number,
imdbVotes: Number,
imdbID: String,
response: Boolean
});

I am typecasting runtime and IMDB ratings to integers in order to be able to use them with the D3.js library. As well this provide an added layer of validation to make sure that I always get the data with the type I except.

Front-end application

For our front-end application I used the javascript framework Angular.

I wrote a simple service that uses the $http object to query the different APIs.

filmy.service('filmyService', ['$http', function($http) {
    function requestExternal(method, endpoint) {
return $http({
method: method,
url: 'http://www.omdbapi.com/' + endpoint,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
}
    function deleteExternal(method, id) {
return $http({
method: method,
url: 'api/films/' + id,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
}
    function requestInternal(method, data) {
return $http({
method: method,
url: 'api/films',
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Access-Control-Allow-Origin' : '*', 'Access-Control-Allow-Headers' : 'Origin, X-Requested-With, Content-Type, Accept'},
data: data
});
}
}]);

The service provides three public functions.

/*
* Makes a GET call to the OMDB or thin client depending on collection.
* {boolean}: collection
* {endpoint}: string
* Returns a promise.
*/
getMovies(collection, endpoint);
/*
* Makes a DELETE call to the thin client.
* {id}: string
* Returns a promise.
*/
deleteMovie(id);
/*
* Makes a POST call to the thin client passing it the
* movie object.
* {data}: object
* Returns a promise.
*/
saveMovie(data);

Github Repos: