added non-aj cineasts example
renamed all cineasts examples in pom.xml
This commit is contained in:
@@ -3,11 +3,11 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.neo4j.examples</groupId>
|
||||
<artifactId>movies-aspects</artifactId>
|
||||
<artifactId>cineasts-aspects</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>Movies</name>
|
||||
<name>Cineasts.net Aspects</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>movies-rest</artifactId>
|
||||
<artifactId>cineasts-rest</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>Movies over REST</name>
|
||||
<name>Cineasts over REST</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
12
spring-data-neo4j-examples/cineasts/.gitignore
vendored
Normal file
12
spring-data-neo4j-examples/cineasts/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
.DS_Store
|
||||
*.ipr
|
||||
*.iws
|
||||
*.iml
|
||||
*.zip
|
||||
data
|
||||
target
|
||||
*.log
|
||||
tmp
|
||||
.classpath
|
||||
.project
|
||||
.settings
|
||||
@@ -7,7 +7,7 @@
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>Movies</name>
|
||||
<name>Cineasts.net</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -16,7 +16,6 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<neo4j.version>1.5.M02</neo4j.version>
|
||||
<spring-data-graph.version>2.0.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<aspectj.version>1.6.12.M1</aspectj.version>
|
||||
<org.slf4j-version>1.6.1</org.slf4j-version>
|
||||
</properties>
|
||||
|
||||
@@ -176,7 +175,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-aspects</artifactId>
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
<version>${spring-data-graph.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -222,11 +221,11 @@
|
||||
<version>1.7.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!--dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
</dependency-->
|
||||
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
@@ -234,12 +233,6 @@
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||
<version>1.0.0.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Neo4j Libraries -->
|
||||
|
||||
<dependency>
|
||||
@@ -318,7 +311,7 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<!--plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>1.2</version>
|
||||
@@ -357,7 +350,7 @@
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugin-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.neo4j.cineasts.domain.Rating;
|
||||
import org.neo4j.cineasts.domain.User;
|
||||
import org.neo4j.cineasts.repository.MovieRepository;
|
||||
import org.neo4j.cineasts.repository.PersonRepository;
|
||||
import org.neo4j.cineasts.service.CineastsRepository;
|
||||
import org.neo4j.cineasts.repository.UserRepository;
|
||||
import org.neo4j.cineasts.service.CineastsUserDetailsService;
|
||||
import org.neo4j.cineasts.service.DatabasePopulator;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
@@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -34,8 +35,12 @@ public class MovieController {
|
||||
@Autowired
|
||||
private PersonRepository personRepository;
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
@Autowired
|
||||
private CineastsUserDetailsService userDetailsService;
|
||||
@Autowired
|
||||
Neo4jOperations template;
|
||||
@Autowired
|
||||
private DatabasePopulator populator;
|
||||
private static final Logger log = LoggerFactory.getLogger(MovieController.class);
|
||||
|
||||
@@ -61,7 +66,7 @@ public class MovieController {
|
||||
final int stars = movie.getStars();
|
||||
model.addAttribute("stars", stars);
|
||||
Rating rating = null;
|
||||
if (user!=null) rating = movie.getRelationshipTo(user, Rating.class, "RATED");
|
||||
if (user!=null) rating = template.getRelationshipBetween(movie, user, Rating.class, "RATED");
|
||||
if (rating == null) rating = new Rating().rate(stars,null);
|
||||
model.addAttribute("userRating",rating);
|
||||
}
|
||||
@@ -75,7 +80,7 @@ public class MovieController {
|
||||
if (user != null && movie != null) {
|
||||
int stars1 = stars==null ? -1 : stars;
|
||||
String comment1 = comment!=null ? comment.trim() : null;
|
||||
user.rate(movie, stars1, comment1);
|
||||
user.rate(template,movie, stars1, comment1);
|
||||
}
|
||||
return singleMovieView(model,movieId);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
package org.neo4j.cineasts.domain;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.annotation.RelatedTo;
|
||||
import org.springframework.data.neo4j.annotation.RelatedToVia;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
|
||||
import java.util.*;
|
||||
@@ -19,6 +15,7 @@ import static org.neo4j.graphdb.Direction.INCOMING;
|
||||
*/
|
||||
@NodeEntity
|
||||
public class Movie {
|
||||
@GraphId Long nodeId;
|
||||
|
||||
@Indexed
|
||||
String id;
|
||||
@@ -34,11 +31,11 @@ public class Movie {
|
||||
@RelatedTo(type = "ACTS_IN", direction = INCOMING)
|
||||
Set<Person> actors;
|
||||
|
||||
@RelatedToVia(elementClass = Role.class, type = "ACTS_IN", direction = INCOMING)
|
||||
@RelatedToVia(type = "ACTS_IN", direction = INCOMING)
|
||||
Iterable<Role> roles;
|
||||
|
||||
@RelatedToVia(elementClass = Rating.class, type = "RATED", direction = INCOMING)
|
||||
Iterable<Rating> ratings;
|
||||
@RelatedToVia(type = "RATED", direction = INCOMING)
|
||||
@Fetch Iterable<Rating> ratings;
|
||||
private String language;
|
||||
private String imdbId;
|
||||
private String tagline;
|
||||
@@ -224,5 +221,22 @@ public class Movie {
|
||||
int numberOfParts = parts.length;
|
||||
return numberOfParts > 0 ? parts[numberOfParts-1] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Movie movie = (Movie) o;
|
||||
if (nodeId == null) return super.equals(o);
|
||||
return nodeId.equals(movie.nodeId);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return nodeId != null ? nodeId.hashCode() : super.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package org.neo4j.cineasts.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.annotation.RelatedTo;
|
||||
import org.springframework.data.neo4j.annotation.RelatedToVia;
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -15,6 +14,7 @@ import java.util.Set;
|
||||
*/
|
||||
@NodeEntity
|
||||
public class Person {
|
||||
@GraphId Long nodeId;
|
||||
@Indexed
|
||||
String id;
|
||||
@Indexed(indexType=IndexType.FULLTEXT, indexName = "people")
|
||||
@@ -100,7 +100,7 @@ public class Person {
|
||||
}
|
||||
|
||||
@RelatedTo(elementClass = Movie.class, type = "DIRECTED")
|
||||
private Set<Movie> directedMovies;
|
||||
private Set<Movie> directedMovies=new HashSet<Movie>();
|
||||
|
||||
public Set<Movie> getDirectedMovies() {
|
||||
return directedMovies;
|
||||
@@ -117,10 +117,27 @@ public class Person {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public Role playedIn(Movie movie, String roleName) {
|
||||
Role role = relateTo(movie, Role.class, "ACTS_IN");
|
||||
public Role playedIn(Neo4jOperations template,Movie movie, String roleName) {
|
||||
Role role = template.createRelationshipBetween(this, movie, Role.class, "ACTS_IN",false);
|
||||
role.setName(roleName);
|
||||
return role;
|
||||
return template.save(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Person person = (Person) o;
|
||||
if (nodeId == null) return super.equals(o);
|
||||
return nodeId.equals(person.nodeId);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return nodeId != null ? nodeId.hashCode() : super.hashCode();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.neo4j.cineasts.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.EndNode;
|
||||
import org.springframework.data.neo4j.annotation.RelationshipEntity;
|
||||
import org.springframework.data.neo4j.annotation.StartNode;
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
@@ -12,9 +10,9 @@ import org.springframework.data.neo4j.annotation.StartNode;
|
||||
public class Rating {
|
||||
private static final int MAX_STARS = 5;
|
||||
private static final int MIN_STARS = 0;
|
||||
@GraphId Long id;
|
||||
|
||||
@StartNode
|
||||
User user;
|
||||
@StartNode User user;
|
||||
@EndNode Movie movie;
|
||||
|
||||
int stars;
|
||||
@@ -49,4 +47,21 @@ public class Rating {
|
||||
if (comment!=null && !comment.isEmpty()) this.comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Rating rating = (Rating) o;
|
||||
if (id == null) return super.equals(o);
|
||||
return id.equals(rating.id);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id != null ? id.hashCode() : super.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.neo4j.cineasts.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.EndNode;
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.RelationshipEntity;
|
||||
import org.springframework.data.neo4j.annotation.StartNode;
|
||||
|
||||
@@ -10,6 +11,7 @@ import org.springframework.data.neo4j.annotation.StartNode;
|
||||
*/
|
||||
@RelationshipEntity
|
||||
public class Role {
|
||||
@GraphId Long id;
|
||||
@EndNode Movie movie;
|
||||
@StartNode Person actor;
|
||||
|
||||
@@ -35,4 +37,21 @@ public class Role {
|
||||
public String toString() {
|
||||
return String.format("%s acts as %s in %s", actor, name, movie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Role role = (Role) o;
|
||||
if (id == null) return super.equals(o);
|
||||
return id.equals(role.id);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id != null ? id.hashCode() : super.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ package org.neo4j.cineasts.domain;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.annotation.RelatedTo;
|
||||
import org.springframework.data.neo4j.annotation.RelatedToVia;
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
@@ -14,6 +12,8 @@ import java.util.Set;
|
||||
|
||||
@NodeEntity
|
||||
public class User {
|
||||
@GraphId Long nodeId;
|
||||
|
||||
private static final String SALT = "cewuiqwzie";
|
||||
public static final String FRIEND = "FRIEND";
|
||||
public static final String RATED = "RATED";
|
||||
@@ -38,22 +38,23 @@ public class User {
|
||||
return new Md5PasswordEncoder().encodePassword(password, SALT);
|
||||
}
|
||||
|
||||
@RelatedToVia(elementClass = Rating.class, type = RATED)
|
||||
Iterable<Rating> ratings;
|
||||
@RelatedToVia(type = RATED)
|
||||
@Fetch Iterable<Rating> ratings;
|
||||
|
||||
@RelatedTo(elementClass = Movie.class, type = RATED)
|
||||
@RelatedTo(type = RATED)
|
||||
Set<Movie> favorites;
|
||||
|
||||
|
||||
@RelatedTo(elementClass = User.class, type = FRIEND, direction = Direction.BOTH)
|
||||
Set<User> friends;
|
||||
@RelatedTo(type = FRIEND, direction = Direction.BOTH)
|
||||
@Fetch Set<User> friends;
|
||||
|
||||
public void addFriend(User friend) {
|
||||
this.friends.add(friend);
|
||||
}
|
||||
|
||||
public Rating rate(Movie movie, int stars, String comment) {
|
||||
return relateTo(movie, Rating.class, RATED).rate(stars, comment);
|
||||
public Rating rate(Neo4jOperations template, Movie movie, int stars, String comment) {
|
||||
final Rating rating = template.createRelationshipBetween(this, movie, Rating.class, RATED, false).rate(stars, comment);
|
||||
return template.save(rating);
|
||||
}
|
||||
|
||||
public Collection<Rating> getRatings() {
|
||||
@@ -114,4 +115,20 @@ public class User {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
User user = (User) o;
|
||||
if (nodeId == null) return super.equals(o);
|
||||
return nodeId.equals(user.nodeId);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return nodeId != null ? nodeId.hashCode() : super.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package org.neo4j.cineasts.movieimport;
|
||||
|
||||
import org.neo4j.cineasts.domain.*;
|
||||
import org.neo4j.cineasts.domain.Movie;
|
||||
import org.neo4j.cineasts.domain.Person;
|
||||
import org.neo4j.cineasts.domain.Roles;
|
||||
import org.neo4j.cineasts.repository.MovieRepository;
|
||||
import org.neo4j.cineasts.repository.PersonRepository;
|
||||
import org.neo4j.cineasts.service.CineastsRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -21,15 +23,16 @@ public class MovieDbImportService {
|
||||
MovieDbJsonMapper movieDbJsonMapper = new MovieDbJsonMapper();
|
||||
|
||||
@Autowired
|
||||
MovieRepository movieRepository;
|
||||
private MovieRepository movieRepository;
|
||||
@Autowired
|
||||
PersonRepository personRepository;
|
||||
private PersonRepository personRepository;
|
||||
|
||||
@Autowired
|
||||
MovieDbApiClient client;
|
||||
private MovieDbApiClient client;
|
||||
|
||||
@Autowired
|
||||
MovieDbLocalStorage localStorage;
|
||||
private MovieDbLocalStorage localStorage;
|
||||
@Autowired private Neo4jOperations template;
|
||||
|
||||
@Transactional
|
||||
public Map<Integer, String> importMovies(Map<Integer, Integer> ranges) {
|
||||
@@ -68,7 +71,7 @@ public class MovieDbImportService {
|
||||
Map data = loadMovieData(movieId);
|
||||
if (data.containsKey("not_found")) throw new RuntimeException("Data for Movie "+movieId+" not found.");
|
||||
movieDbJsonMapper.mapToMovie(data, movie);
|
||||
movie.persist();
|
||||
movieRepository.save(movie);
|
||||
relatePersonsToMovie(movie, data);
|
||||
return movie;
|
||||
}
|
||||
@@ -84,7 +87,7 @@ public class MovieDbImportService {
|
||||
}
|
||||
|
||||
private void relatePersonsToMovie(Movie movie, Map data) {
|
||||
Collection<Map> cast = (Collection<Map>) data.get("cast");
|
||||
@SuppressWarnings("unchecked") Collection<Map> cast = (Collection<Map>) data.get("cast");
|
||||
for (Map entry : cast) {
|
||||
String id = "" + entry.get("id");
|
||||
String jobName = (String) entry.get("job");
|
||||
@@ -99,7 +102,7 @@ public class MovieDbImportService {
|
||||
person.directed(movie);
|
||||
break;
|
||||
case ACTS_IN:
|
||||
person.playedIn(movie, (String) entry.get("character"));
|
||||
person.playedIn(template,movie, (String) entry.get("character"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +121,7 @@ public class MovieDbImportService {
|
||||
if (data.containsKey("not_found")) throw new RuntimeException("Data for Person "+personId+" not found.");
|
||||
Person newPerson=new Person(personId,null);
|
||||
movieDbJsonMapper.mapToPerson(data, newPerson);
|
||||
return newPerson.persist();
|
||||
return personRepository.save(newPerson);
|
||||
}
|
||||
|
||||
private Map loadPersonData(String personId) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.neo4j.annotation.Query;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.NamedIndexRepository;
|
||||
import org.springframework.data.neo4j.repository.RelationshipOperationsRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -15,7 +16,7 @@ import java.util.List;
|
||||
* @author mh
|
||||
* @since 02.04.11
|
||||
*/
|
||||
public interface MovieRepository extends GraphRepository<Movie>, NamedIndexRepository<Movie> {
|
||||
public interface MovieRepository extends GraphRepository<Movie>, NamedIndexRepository<Movie>, RelationshipOperationsRepository<Movie> {
|
||||
Movie findById(String id);
|
||||
|
||||
Page<Movie> findByTitleLike(String title, Pageable page);
|
||||
|
||||
@@ -2,11 +2,12 @@ package org.neo4j.cineasts.repository;
|
||||
|
||||
import org.neo4j.cineasts.domain.Person;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.RelationshipOperationsRepository;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 02.04.11
|
||||
*/
|
||||
public interface PersonRepository extends GraphRepository<Person> {
|
||||
public interface PersonRepository extends GraphRepository<Person>, RelationshipOperationsRepository<Person> {
|
||||
Person findById(String id);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package org.neo4j.cineasts.repository;
|
||||
|
||||
import org.neo4j.cineasts.domain.User;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.RelationshipOperationsRepository;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 02.04.11
|
||||
*/
|
||||
public interface UserRepository extends GraphRepository<User> {
|
||||
public interface UserRepository extends GraphRepository<User>, RelationshipOperationsRepository<User> {
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package org.neo4j.cineasts.service;
|
||||
|
||||
import org.neo4j.cineasts.repository.MovieRepository;
|
||||
import org.neo4j.kernel.AbstractGraphDatabase;
|
||||
import org.neo4j.cineasts.domain.*;
|
||||
import org.neo4j.cineasts.domain.Movie;
|
||||
import org.neo4j.cineasts.domain.User;
|
||||
import org.neo4j.cineasts.movieimport.MovieDbImportService;
|
||||
import org.neo4j.cineasts.repository.MovieRepository;
|
||||
import org.neo4j.cineasts.repository.UserRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -23,10 +24,9 @@ import static java.util.Arrays.asList;
|
||||
@Service
|
||||
public class DatabasePopulator {
|
||||
|
||||
@Autowired
|
||||
Neo4jTemplate ctx;
|
||||
@Autowired
|
||||
MovieRepository movieRepository;
|
||||
@Autowired UserRepository userRepository;
|
||||
@Autowired MovieRepository movieRepository;
|
||||
@Autowired Neo4jOperations template;
|
||||
|
||||
@Autowired
|
||||
MovieDbImportService importService;
|
||||
@@ -34,8 +34,8 @@ public class DatabasePopulator {
|
||||
|
||||
@Transactional
|
||||
public List<Movie> populateDatabase() {
|
||||
User me = new User("micha", "Micha", "password", User.Roles.ROLE_ADMIN,User.Roles.ROLE_USER).persist();
|
||||
User ollie = new User("ollie", "Olliver", "password",User.Roles.ROLE_USER).persist();
|
||||
User me = userRepository.save(new User("micha", "Micha", "password", User.Roles.ROLE_ADMIN,User.Roles.ROLE_USER));
|
||||
User ollie = userRepository.save(new User("ollie", "Olliver", "password",User.Roles.ROLE_USER));
|
||||
me.addFriend(ollie);
|
||||
List<Integer> ids = asList(19995 , 194, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 13, 20526, 11, 1893, 1892, 1894, 168, 193, 200, 157, 152, 201, 154, 12155, 58, 285, 118, 22, 392, 5255, 568, 9800, 497, 101, 120, 121, 122);
|
||||
List<Movie> result=new ArrayList<Movie>(ids.size());
|
||||
@@ -44,12 +44,13 @@ public class DatabasePopulator {
|
||||
}
|
||||
|
||||
//me.rate(repository.getMovie("13"),5,"Inspiring");
|
||||
me.rate(movieRepository.findById("603"),5,"Best of the series");
|
||||
final Movie movie = movieRepository.findById("603");
|
||||
me.rate(template, movie,5,"Best of the series");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void cleanDb() {
|
||||
new Neo4jDatabaseCleaner((AbstractGraphDatabase) ctx.getGraphDatabaseService()).cleanDb();
|
||||
new Neo4jDatabaseCleaner(template).cleanDb();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package org.neo4j.cineasts.service;
|
||||
|
||||
import org.neo4j.cineasts.domain.Movie;
|
||||
import org.neo4j.cineasts.domain.Rating;
|
||||
import org.neo4j.cineasts.domain.User;
|
||||
import org.neo4j.graphdb.traversal.Evaluators;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.neo4j.kernel.Uniqueness;
|
||||
import org.springframework.data.neo4j.core.EntityPath;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.neo4j.graphdb.DynamicRelationshipType.withName;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 04.04.11
|
||||
*/
|
||||
public class FriendsMovieRecommendations {
|
||||
private final Map<Movie, MovieRating> ratings = new HashMap<Movie, MovieRating>();
|
||||
private final int ratingDistance;
|
||||
|
||||
public static class MovieRating {
|
||||
int stars;
|
||||
int count;
|
||||
public void update(Rating rating, int weight) {
|
||||
this.stars += rating.getStars()*weight;
|
||||
this.count += weight;
|
||||
}
|
||||
public int average() {
|
||||
return count == 0 ? 0 : stars / count;
|
||||
}
|
||||
public String toString() {
|
||||
return String.valueOf(average());
|
||||
}
|
||||
|
||||
}
|
||||
public FriendsMovieRecommendations(int ratingDistance) {
|
||||
this.ratingDistance = ratingDistance;
|
||||
}
|
||||
|
||||
public Map<Movie, ?> getRecommendationsFor(User user) {
|
||||
TraversalDescription traversal = Traversal.description().breadthFirst()
|
||||
.uniqueness(Uniqueness.NODE_GLOBAL).relationships(withName(User.FRIEND))
|
||||
.evaluator(Evaluators.toDepth(ratingDistance)).evaluator(Evaluators.excludeStartPosition());
|
||||
|
||||
Iterable result = user.findAllPathsByTraversal(traversal);
|
||||
Iterable<EntityPath<User,User>> friends = (Iterable<EntityPath<User,User>>)result;
|
||||
for (EntityPath<User,User> path : friends) {
|
||||
int weight = ratingDistance - path.length();
|
||||
User friend = path.endEntity();
|
||||
aggregateRatings(friend,weight);
|
||||
}
|
||||
for (Rating rating : user.getRatings()) {
|
||||
ratings.remove(rating.getMovie());
|
||||
}
|
||||
return ratings;
|
||||
}
|
||||
|
||||
private void aggregateRatings(User friend, int weight) {
|
||||
for (Rating rating : friend.getRatings()) {
|
||||
obtainRating(rating.getMovie()).update(rating, weight);
|
||||
}
|
||||
}
|
||||
|
||||
private MovieRating obtainRating(Movie movie) {
|
||||
if (!ratings.containsKey(movie)) {
|
||||
ratings.put(movie, new MovieRating());
|
||||
}
|
||||
return ratings.get(movie);
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package org.neo4j.cineasts.service;
|
||||
|
||||
import org.neo4j.cineasts.domain.Movie;
|
||||
import org.neo4j.cineasts.domain.User;
|
||||
import org.neo4j.cineasts.repository.MovieRepository;
|
||||
import org.neo4j.graphdb.Path;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.traversal.Evaluation;
|
||||
import org.neo4j.graphdb.traversal.Evaluator;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.neo4j.kernel.Uniqueness;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.neo4j.graphdb.Direction.OUTGOING;
|
||||
import static org.neo4j.graphdb.DynamicRelationshipType.withName;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 04.04.11
|
||||
*/
|
||||
class MovieRecommendations implements Evaluator {
|
||||
private final Map<Long,int[]> ratings=new HashMap<Long, int[]>();
|
||||
private final int ratingDistance;
|
||||
private MovieRepository movieRepository;
|
||||
|
||||
public MovieRecommendations(MovieRepository movieRepository, int ratingDistance) {
|
||||
this.movieRepository = movieRepository;
|
||||
this.ratingDistance = ratingDistance;
|
||||
}
|
||||
|
||||
public Map<Movie, ?> getRecommendationsFor(User user) {
|
||||
TraversalDescription traversal= Traversal.description().breadthFirst()
|
||||
.uniqueness(Uniqueness.NODE_PATH)
|
||||
.relationships(withName(User.FRIEND))
|
||||
.relationships(withName(User.RATED), OUTGOING)
|
||||
.evaluator(this);
|
||||
return averageRecommendations(user, traversal);
|
||||
}
|
||||
|
||||
private Map<Movie, Integer> averageRecommendations(User user, TraversalDescription traversal) { // todo sort, limit
|
||||
Map<Movie,Integer> result=new HashMap<Movie, Integer>();
|
||||
for (Movie movie : movieRepository.findAllByTraversal(user, traversal)) {
|
||||
final int[] rating = ratings.get(movie.getNodeId());
|
||||
result.put(movie, rating[1]==0 ? 0 : rating[0]/rating[1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Evaluation evaluate(Path path) {
|
||||
final int distance = path.length() - 1;
|
||||
if (distance > ratingDistance) return Evaluation.EXCLUDE_AND_PRUNE;
|
||||
Relationship rated = path.lastRelationship();
|
||||
if (rated != null && rated.getType().name().equals(User.RATED)) {
|
||||
if (distance == 0) return Evaluation.EXCLUDE_AND_PRUNE; // my rated movies
|
||||
updateRating(rated, distance);
|
||||
return Evaluation.INCLUDE_AND_PRUNE;
|
||||
}
|
||||
System.out.println();
|
||||
return Evaluation.EXCLUDE_AND_CONTINUE;
|
||||
}
|
||||
|
||||
private void updateRating(Relationship rated, int distance) {
|
||||
final long movieId = rated.getEndNode().getId();
|
||||
int[] rating = obtainRating(movieId);
|
||||
|
||||
int weight = ratingDistance - distance;
|
||||
final Integer stars = (Integer) rated.getProperty("stars", 0);
|
||||
rating[0] += weight * stars;
|
||||
rating[1] += weight;
|
||||
}
|
||||
|
||||
private int[] obtainRating(long movieId) {
|
||||
if (!ratings.containsKey(movieId)) {
|
||||
ratings.put(movieId,new int[2]);
|
||||
}
|
||||
return ratings.get(movieId);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
package org.neo4j.cineasts.service;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.index.IndexManager;
|
||||
import org.neo4j.kernel.AbstractGraphDatabase;
|
||||
import org.springframework.data.neo4j.support.DelegatingGraphDatabase;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -16,10 +14,10 @@ import java.util.Map;
|
||||
* @since 02.03.11
|
||||
*/
|
||||
public class Neo4jDatabaseCleaner {
|
||||
private AbstractGraphDatabase graph;
|
||||
private GraphDatabaseService graph;
|
||||
|
||||
public Neo4jDatabaseCleaner(AbstractGraphDatabase graph) {
|
||||
this.graph = graph;
|
||||
public Neo4jDatabaseCleaner(Neo4jOperations template) {
|
||||
this.graph = ((DelegatingGraphDatabase)template.getGraphDatabase()).getGraphDatabaseService();
|
||||
}
|
||||
|
||||
public Map<String, Object> cleanDb() {
|
||||
|
||||
@@ -4,8 +4,10 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.cineasts.repository.MovieRepository;
|
||||
import org.neo4j.cineasts.repository.PersonRepository;
|
||||
import org.neo4j.cineasts.repository.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -30,18 +32,21 @@ public class DomainTest {
|
||||
@Autowired
|
||||
protected UserRepository userRepository;
|
||||
|
||||
@Autowired Neo4jOperations template;
|
||||
@Autowired PersonRepository personRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actorCanPlayARoleInAMovie() {
|
||||
Person tomHanks = new Person("1","Tom Hanks").persist();
|
||||
Movie forestGump = new Movie("1", "Forrest Gump").persist();
|
||||
Person tomHanks = template.save(new Person("1", "Tom Hanks"));
|
||||
Movie forestGump = template.save(new Movie("1", "Forrest Gump"));
|
||||
|
||||
Role role = tomHanks.playedIn(forestGump, "Forrest");
|
||||
Role role = tomHanks.playedIn(template, forestGump, "Forrest");
|
||||
|
||||
Movie foundForestGump = this.movieRepository.findByPropertyValue(null, "id", "1");
|
||||
Movie foundForestGump = this.movieRepository.findById("1");
|
||||
|
||||
assertEquals("created and looked up movie equal", forestGump, foundForestGump);
|
||||
Role firstRole = foundForestGump.getRoles().iterator().next();
|
||||
@@ -51,7 +56,7 @@ public class DomainTest {
|
||||
|
||||
@Test
|
||||
public void canFindMovieByTitleQuery() {
|
||||
Movie forestGump = new Movie("1", "Forrest Gump").persist();
|
||||
Movie forestGump = template.save(new Movie("1", "Forrest Gump"));
|
||||
Iterator<Movie> queryResults = movieRepository.findAllByQuery("search", "title", "Forre*").iterator();
|
||||
assertTrue("found movie by query",queryResults.hasNext());
|
||||
Movie foundMovie = queryResults.next();
|
||||
@@ -61,12 +66,12 @@ public class DomainTest {
|
||||
|
||||
@Test
|
||||
public void userCanRateMovie() {
|
||||
Movie movie= new Movie("1","Forrest Gump").persist();
|
||||
User user = new User("ich","Micha","password").persist();
|
||||
Rating awesome = user.rate(movie, 5, "Awesome");
|
||||
Movie movie = template.save(new Movie("1", "Forrest Gump"));
|
||||
User user = template.save(new User("ich", "Micha", "password"));
|
||||
Rating awesome = user.rate(template, movie, 5, "Awesome");
|
||||
|
||||
|
||||
User foundUser = userRepository.findByPropertyValue("login", "ich");
|
||||
user = userRepository.findByPropertyValue("login", "ich");
|
||||
movie = movieRepository.findById("1");
|
||||
Rating rating = user.getRatings().iterator().next();
|
||||
assertEquals(awesome,rating);
|
||||
assertEquals("Awesome",rating.getComment());
|
||||
@@ -75,7 +80,7 @@ public class DomainTest {
|
||||
}
|
||||
@Test
|
||||
public void canFindUserByLogin() {
|
||||
User user = new User("ich","Micha","password").persist();
|
||||
User user = template.save(new User("ich", "Micha", "password"));
|
||||
User foundUser = userRepository.findByPropertyValue("login", "ich");
|
||||
assertEquals(user, foundUser);
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ import org.neo4j.cineasts.domain.MovieRecommendation;
|
||||
import org.neo4j.cineasts.domain.Rating;
|
||||
import org.neo4j.cineasts.domain.User;
|
||||
import org.neo4j.cineasts.repository.MovieRepository;
|
||||
import org.neo4j.cineasts.repository.UserRepository;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -29,25 +31,26 @@ import static org.junit.Assert.assertTrue;
|
||||
@ContextConfiguration({"/movies-test-context.xml"})
|
||||
@Transactional
|
||||
public class MoviesRepositoryTest {
|
||||
@Autowired
|
||||
MovieRepository movieRepository;
|
||||
@Autowired MovieRepository movieRepository;
|
||||
@Autowired UserRepository userRepository;
|
||||
@Autowired Neo4jOperations template;
|
||||
|
||||
@Test
|
||||
public void testGetMovie() throws Exception {
|
||||
Movie movie = new Movie("1", "Test-Movie").persist();
|
||||
Movie movie = movieRepository.save(new Movie("1", "Test-Movie"));
|
||||
Movie found = movieRepository.findById("1");
|
||||
assertEquals("movie found by id", movie, found);
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testGetMovieRecommendations() throws Exception {
|
||||
Movie movie = new Movie("1", "Test-Movie").persist();
|
||||
Movie movie2 = new Movie("2", "Test-Movie2").persist();
|
||||
User user=new User("me","me","me").persist();
|
||||
user.rate(movie,3,"me");
|
||||
User friend=new User("friend","friend","friend").persist();
|
||||
friend.rate(movie,5,"friend");
|
||||
friend.rate(movie2,3,"friend2");
|
||||
Movie movie = movieRepository.save(new Movie("1", "Test-Movie"));
|
||||
Movie movie2 = movieRepository.save(new Movie("2", "Test-Movie2"));
|
||||
User user = userRepository.save(new User("me", "me", "me"));
|
||||
user.rate(template,movie,3,"me");
|
||||
User friend = userRepository.save(new User("friend", "friend", "friend"));
|
||||
friend.rate(template, movie, 5, "friend");
|
||||
friend.rate(template, movie2, 3, "friend2");
|
||||
assertEquals(2,movieRepository.count());
|
||||
final List<MovieRecommendation> recommendations = movieRepository.getRecommendations(user);
|
||||
assertEquals("one recommendation", 1, recommendations.size());
|
||||
@@ -56,9 +59,10 @@ public class MoviesRepositoryTest {
|
||||
}
|
||||
@Test
|
||||
public void testRateMovie() throws Exception {
|
||||
Movie movie = new Movie("1", "Test-Movie").persist();
|
||||
User user=new User("me","me","me").persist();
|
||||
user.rate(movie, 5, "comment");
|
||||
Movie movie = movieRepository.save(new Movie("1", "Test-Movie"));
|
||||
User user = userRepository.save(new User("me", "me", "me"));
|
||||
user.rate(template, movie, 5, "comment");
|
||||
movie = movieRepository.findById("1");
|
||||
final Rating rating = IteratorUtil.first(movie.getRatings());
|
||||
assertEquals("rating stars", 5, rating.getStars());
|
||||
assertEquals("rating comment", "comment", rating.getComment());
|
||||
@@ -68,9 +72,9 @@ public class MoviesRepositoryTest {
|
||||
|
||||
@Test
|
||||
public void testFindTwoMovies() throws Exception {
|
||||
Movie movie1 = new Movie("1", "Test-Movie1").persist();
|
||||
Movie movie2 = new Movie("2", "Test-Movie2").persist();
|
||||
Movie movie3 = new Movie("3", "Another-Movie3").persist();
|
||||
Movie movie1 = movieRepository.save(new Movie("1", "Test-Movie1"));
|
||||
Movie movie2 = movieRepository.save(new Movie("2", "Test-Movie2"));
|
||||
Movie movie3 = movieRepository.save(new Movie("3", "Another-Movie3"));
|
||||
List<Movie> found = movieRepository.findByTitleLike("Test*", new PageRequest(0, 2)).getContent();
|
||||
assertEquals("2 movies found", 2, found.size());
|
||||
assertEquals("2 correct movies found by query", new HashSet<Movie>(asList(movie1, movie2)), new HashSet<Movie>(found));
|
||||
@@ -78,9 +82,9 @@ public class MoviesRepositoryTest {
|
||||
|
||||
@Test
|
||||
public void testFindTwoMoviesButRestrictToOne() throws Exception {
|
||||
Movie movie1 = new Movie("1", "Test-Movie1").persist();
|
||||
Movie movie2 = new Movie("2", "Test-Movie2").persist();
|
||||
Movie movie3 = new Movie("3", "Another-Movie3").persist();
|
||||
Movie movie1 = movieRepository.save(new Movie("1", "Test-Movie1"));
|
||||
Movie movie2 = movieRepository.save(new Movie("2", "Test-Movie2"));
|
||||
Movie movie3 = movieRepository.save(new Movie("3", "Another-Movie3"));
|
||||
List<Movie> found = movieRepository.findByTitleLike("Test*", new PageRequest(0, 1)).getContent();
|
||||
assertEquals("1 movie found",1,found.size());
|
||||
assertTrue("1 correct movie found by query", found.get(0).getTitle().startsWith("Test"));
|
||||
|
||||
Reference in New Issue
Block a user