This blog details how to build a recommendation system using Neo4j. The focus is on recommending movies to users based on their reading histories and ratings. It covers the setup of Neo4j, mapping data into Java with Neo4j Object Graph Mapper (Neo4j-OGM), and crafting Cypher queries for recommendations. Additionally, it includes guidance on setting up and using Neo4j Aura, Neo4j’s cloud-hosted database service.
Setting Up Your Environment
- Install Neo4j:
- Local: Download and install Neo4j Desktop.
- Cloud: Sign up for Neo4j Aura and create a database instance.
2. Add Neo4j-OGM dependency: Add Neo4j OGM to your pom.xml if you are using Maven:
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
<version>3.2.31</version>
</dependency>
3. Configure Neo4j-OGM: Set up neo4j-ogm.properties or configure programmatically:
dbms.url=bolt://localhost:7687
dbms.username=neo4j
dbms.password=password
Adding Data Into Neo4j
I used the Neo4j Browser to add data into the Neo4j database. This involved manually entering Cypher queries to create nodes and relationships. For example:
// Create Users
CREATE (u1:User {id: 1, name: 'Alice'})
CREATE (u2:User {id: 2, name: 'Bob'})
// Create Movies
CREATE (m1:Movie {id: 1, title: 'Inception', genre: 'Sci-Fi', rating: 9})
CREATE (m2:Movie {id: 2, title: 'The Matrix', genre: 'Sci-Fi', rating: 8})
CREATE (m3:Movie {id: 3, title: 'The Godfather', genre: 'Drama', rating: 10})
// Create Relationships
MATCH (u1:User {name: 'Alice'}), (m1:Movie {title: 'Inception'})
CREATE (u1)-[:LIKES]->(m1)
MATCH (u2:User {name: 'Bob'}), (m2:Movie {title: 'The Matrix'})
CREATE (u2)-[:LIKES]->(m2)
Mapping Your Data With Neo4j-OGM
- Define Java classes: Create Java classes that map to your Neo4j nodes and relationships. For instance, for a movie recommendation system:
@NodeEntity
public class User {
@Id @GeneratedValue
private Long id;
private String name;
@Relationship(type = "LIKES", direction = Relationship.Direction.OUTGOING)
private Set<Movie> likedMovies = new HashSet<>();
}
@NodeEntity
public class Movie {
@Id @GeneratedValue
private Long id;
private String title;
private String genre;
}
2. Set up Neo4j-OGM Configuration: Create a configuration class to handle the connection:
import org.neo4j.ogm.config.Configuration;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
public class Neo4jConfig {
private static final String URL = "bolt://localhost:7687";
private static final String USER = "neo4j";
private static final String PASSWORD = "password";
private SessionFactory sessionFactory;
public Neo4jConfig() {
Configuration configuration = new Configuration.Builder()
.uri(URL)
.credentials(USER, PASSWORD)
.build();
this.sessionFactory = new SessionFactory(configuration, "your.package");
}
public Session getSession() {
return sessionFactory.openSession();
}
}
Code to Execute Cypher Query From Java
To execute the Cypher query that recommends movies, you can use Neo4j’s Java Driver. Ensure you have the Neo4j Java Driver dependency added to your pom.xml :
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>5.1.0</version>
</dependency>
Here’s a concise Java class that executes the Cypher query to get recommended movies:
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Session;
import org.neo4j.driver.Result;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class RecommendationService {
private final Driver driver;
public RecommendationService(String uri, String user, String password) {
driver = GraphDatabase.driver(uri, AuthTokens.basic(user, password));
}
public void close() {
driver.close();
}
public List<String> getRecommendedMovies(Long userId) {
try (Session session = driver.session()) {
String query = "MATCH (u:User {id: $userId})-[:LIKES]->(m:Movie) " +
"WITH COLLECT(m.genre) AS likedGenres " +
"MATCH (m2:Movie) WHERE m2.genre IN likedGenres " +
"AND NOT EXISTS((u)-[:LIKES]->(m2)) " +
"RETURN m2.title AS recommendedMovie " +
"ORDER BY m2.rating DESC " +
"LIMIT 10";
return session.run(query, Map.of("userId", userId))
.list(record -> record.get("recommendedMovie").asString())
.stream()
.collect(Collectors.toList());
}
}
public static void main(String[] args) {
try (RecommendationService service = new RecommendationService("bolt://localhost:7687", "neo4j", "password")) {
service.getRecommendedMovies(1L).forEach(System.out::println);
}
}
}
Recommendation Queries
- Basic recommendations: Let’s say you want to recommend movies to a user based on their liked genres. You can use a Cypher query to find similar movies:
MATCH (u:User)-[:LIKES]->(m:Movie)
WITH u, COLLECT(m.genre) AS likedGenres
MATCH (m2:Movie)
WHERE m2.genre IN likedGenres
RETURN m2.title AS recommendedMovie
This query collects the genres of movies liked by the user and recommends other movies with similar genres.
2. Filtering and ranking: To refine recommendations, you can consider additional criteria like movie ratings or release dates:
MATCH (u:User)-[:LIKES]->(m:Movie)
WITH u, COLLECT(m.genre) AS likedGenres
MATCH (m2:Movie) WHERE m2.genre IN likedGenres AND NOT EXISTS((u)-[:LIKES]->(m2))
RETURN m2.title AS recommendedMovie
ORDER BY m2.rating DESC
LIMIT 10
This query avoids recommending movies the user has already liked and ranks the suggestions based on their rating.
Using Neo4j Aura
- Connect to Neo4j Aura: Obtain your connection credentials from the Neo4j Aura dashboard and configure your connection settings:
dbms.url=bolt://<aura-uri>:7687
dbms.username=<username>
dbms.password=<password>
2. Deploy and test: Deploy your Java application and test the recommendation queries to ensure they work with Neo4j Aura.
Summary
Building a recommendation system with Neo4j and Neo4j-OGM offers a powerful and efficient way to deliver personalized suggestions by using the inherent relationships in your data. By integrating Neo4j’s graph database capabilities with Neo4j-OGM in Java, you can create a scalable recommendation engine that adapts to users’ preferences and behavior. Using Neo4j Aura for cloud hosting ensures robustness and scalability, allowing you to manage growing datasets effortlessly.
Building a Movie Recommendation System With Neo4j was originally published in Neo4j Developer Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.