November 24, 2018

In this blog post we will explore how to make a simple recommendations website. We will use JavaScript on the clientside to get random recommendations from a set of movies.

What will be covered:

Data structures

Generating random recommendations

Generating random non-duplicated recommendations in a session

Filtering recommendations

Project Codepen

What was built

We built, Animefinder, a website which provides the user with a random Anime recommendation which they might like. It is a small collaboration with senpai Cory Harris.

Motivation

I don’t want to sound dramatic, but looking for an anime to watch is the biggest struggle in my life. Starting a new series is a serious emotional commitment. So for years, I found myself scouring Google for hours before I decided on one. A friend and I hacked together a small Anime Recommender for people like us. We wanted it to be as simple as possible. You just click and get a recommendation along with a reason why we think you should watch it.

Key components

Data structure

An array of object is used. This allows us have an iterable and use reduce and map methods. The objects can then be deconstructed and rendered.

const dataset = [ { name: 'Scary Movie', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'comedy' }, { name: 'Thor', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'action' }, { name: 'White Girls', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'comedy' }, { name: 'Not Another Teen Movie', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'comedy' }, { name: '16 Candles', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'romance' }, { name: 'Mean Girls', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'comedy' }, { name: 'Shrek', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'comedy' }, { name: 'Shrek 2', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'comedy' }, { name: 'Austin Powers', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam faucibus faucibus lectus rhoncus fermentum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', genre: 'comedy' }, ]

Random recommendations

One method of creating recommendations is to pick a random index. Then using this index to display the recommendation. This works but in our use case, it’s not ideal to show the same recommendation.

/** * Gets a random recommendation index * @param {[object]} dataset * @returns {object} random index from the dataset */ const getRandomRecommendation = dataset => { // get the size dataset const datasetN = dataset.length // gets a random from 0 - the number of the end dataset size const randomIndex = Math.floor(Math.random() * Math.floor(datasetN)) return randomIndex } // get the random index const randomIndex = getRandomRecommendation(dataset) console.log(`Random index: ${randomIndex}`)

Non-duplicated recommendations

We would rather go through all the recommendations before repeating them again. That is, only show a recommendation once in a session. This can be accomplished by generating all the recommendations at the start of the session to guarantee that they won’t be shown twice. To do this, create an array of recommendation indices which are shuffled.

/** * Generates a set of random recommendations for a session * @param {[object]} dataset * @returns {[object]} randomized dataset */ const generateRecommendations = dataset => { dataset.sort(() => 0.5 - Math.random()) return dataset } // get random set of recommendations const randomizedRecommendations = generateRecommendations(dataset) console.log(`Random Recommendations: ${JSON.stringify(randomizedRecommendations)}`)

Filtering recommendations

What if we want to filter out some of the recommendations? We need to create a subset of recommendations without the ones we’ve filtered out. We will look at each recommendation object’s genre key, and keep one’s with values which don’t match the filter term.

/** * Filters out dataset based on a search term * @param {[object]} dataset * @param {string} searchTerm * @returns {[object]} filtered dataset */ const filterRecommendations = (dataset, searchTerm) => { const filteredRecommendations = dataset.filter(recommendation => recommendation.genre !== searchTerm) return filteredRecommendations } // get filtered recommendations const filteredRecommendations = filterRecommendations(dataset, 'comedy') console.log(`Filtered Recommendations: ${JSON.stringify(filteredRecommendations)}`)

Conclusion

We looked at generating simple recommendations at random. With a well-curated dataset, we can create an illusion of personalized recommendations. This simple method of generating recommendations leaves a lot to be desired. To generate personalized recommendations we will need to venture data science and machine learning territory. Lets explore this further in the future.