recomendation

PhucLe
Le Phuc 5 months ago
parent 7db94512a7
commit a836e4308f
  1. 25
      BE/src/main/java/org/example/controllers/CategoryController.java
  2. 17
      BE/src/main/java/org/example/controllers/PostController.java
  3. 7
      BE/src/main/java/org/example/controllers/UserController.java
  4. 13
      BE/src/main/java/org/example/models/Category.java
  5. 43
      BE/src/main/java/org/example/models/Post.java
  6. 21
      BE/src/main/java/org/example/objects/FriendDTO.java
  7. 14
      BE/src/main/java/org/example/objects/PostDTO.java
  8. 39
      BE/src/main/java/org/example/objects/PostWithMedia.java
  9. 11
      BE/src/main/java/org/example/repositories/CategoryRepository.java
  10. 25
      BE/src/main/java/org/example/repositories/PostRepository.java
  11. 37
      BE/src/main/java/org/example/repositories/UserRepository.java
  12. 23
      BE/src/main/java/org/example/services/CategoryService.java
  13. 2
      BE/src/main/java/org/example/services/InteractService.java
  14. 7
      BE/src/main/java/org/example/services/PostService.java
  15. 38
      BE/src/main/java/org/example/services/RecommendationService.java
  16. 8
      BE/src/main/java/org/example/services/UserService.java

@ -0,0 +1,25 @@
package org.example.controllers;
import org.example.models.Category;
import org.example.services.CategoryService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/category")
public class CategoryController {
private final CategoryService categoryService;
public CategoryController(CategoryService categoryService) {
this.categoryService = categoryService;
}
@GetMapping("/getAllCategories")
public List<Category> getAllCategories(){
return categoryService.getAllCategories();
}
}

@ -1,15 +1,15 @@
package org.example.controllers;
//import org.example.models.Author;
import org.example.models.Image;
import org.example.models.LikeRequest;
import org.example.models.Post;
import org.example.models.User;
import org.example.models.*;
import org.example.objects.PostDTO;
import org.example.objects.PostWithMedia;
import org.example.repositories.CategoryRepository;
import org.example.repositories.PostRepository;
import org.example.services.PostService;
import org.example.services.RecommendationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@ -25,12 +25,14 @@ public class PostController {
private final PostService postService;
private final PostRepository postRepository;
private final RecommendationService recommendationService;
private final CategoryRepository categoryRepository;
@Autowired
public PostController(PostService postService, PostRepository postRepository, RecommendationService recommendationService) {
public PostController(PostService postService, PostRepository postRepository, RecommendationService recommendationService, CategoryRepository categoryRepository) {
this.postService = postService;
this.postRepository = postRepository;
this.recommendationService = recommendationService;
this.categoryRepository = categoryRepository;
}
@GetMapping("/getAllPosts")
@ -45,17 +47,18 @@ public class PostController {
@PostMapping("/edit/{id}")
public Post updatePost(@PathVariable Long id,@RequestBody PostDTO postDTO) throws IOException {
return postService.editPost(id, postDTO.getTitle(), postDTO.getContent(), postDTO.getImageFile(), postDTO.getVideoFile());
return postService.editPost(id, postDTO.getTitle(), postDTO.getContent(),postDTO.getCategory(), postDTO.getImageFile(), postDTO.getVideoFile());
}
@PostMapping
public Post createPost(
@RequestParam("title") String title,
@RequestParam("content") String content,
@RequestParam("category") Category category,
@RequestParam(value = "imageFile", required = false) MultipartFile imageFile,
@RequestParam(value = "videoFile", required = false) MultipartFile videoFile) throws IOException {
return postService.createPost(title, content, imageFile, videoFile);
return postService.createPost(title, content,category, imageFile, videoFile);
}
@GetMapping("/recommend/{username}")

@ -1,6 +1,7 @@
package org.example.controllers;
import org.example.models.User;
import org.example.objects.FriendDTO;
import org.example.objects.UserDTO;
import org.example.repositories.UserRepository;
import org.example.requests.CreateUserRequest;
@ -36,4 +37,10 @@ public class UserController {
return new ResponseEntity<>(responseUser, HttpStatus.CREATED);
}
@PostMapping("/addFriend")
public ResponseEntity<String> addFriend(@RequestBody FriendDTO friendDTO){
userService.addFriend(friendDTO.getUsername1(),friendDTO.getUsername2());
System.out.println(friendDTO.getUsername1());
return new ResponseEntity<>("Friend added", HttpStatus.CREATED);
}
}

@ -7,6 +7,8 @@ import org.springframework.data.neo4j.core.schema.Relationship;
import java.util.List;
@Node
public class Category {
@Id
@ -14,9 +16,6 @@ public class Category {
private Long id;
private String name;
@Relationship(type = "HAS_POST")
private List<Post> posts;
public Long getId() {
return id;
}
@ -32,12 +31,4 @@ public class Category {
public void setName(String name) {
this.name = name;
}
public List<Post> getPosts() {
return posts;
}
public void setPosts(List<Post> posts) {
this.posts = posts;
}
}

@ -27,39 +27,17 @@ public class Post {
private String author;
private String imgUrl;
private int interactions;
@Relationship(type = "HAS_LIKE", direction = Relationship.Direction.INCOMING)
private List<User> likedByUsers;
@Relationship(type = "HAS_COMMENT", direction = Relationship.Direction.INCOMING)
private List<CommentRelationship> comments;
@Relationship(type = "HAS_SHARE", direction = Relationship.Direction.INCOMING)
private List<ShareRelationship> sharedByUsers;
@Relationship(type = "HAS_POST", direction = Relationship.Direction.INCOMING)
@Relationship(type="HAS_CATEGORY", direction = Relationship.Direction.OUTGOING)
private Category category;
public List<User> getLikedByUsers() {
return likedByUsers;
}
public void setLikedByUsers(List<User> likedByUsers) {
this.likedByUsers = likedByUsers;
}
public void setComments(List<CommentRelationship> comments) {
this.comments = comments;
}
public List<ShareRelationship> getSharedByUsers() {
return sharedByUsers;
public Category getCategory() {
return category;
}
public void setSharedByUsers(List<ShareRelationship> sharedByUsers) {
this.sharedByUsers = sharedByUsers;
public void setCategory(Category category) {
this.category = category;
}
public int getInteractions() {
return interactions;
}
@ -68,22 +46,13 @@ public class Post {
this.interactions = interactions;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
this.imgUrl=imgUrl;
}
public String getAuthor() {

@ -0,0 +1,21 @@
package org.example.objects;
public class FriendDTO {
private String username1,username2;
public String getUsername1() {
return username1;
}
public void setUsername1(String username1) {
this.username1 = username1;
}
public String getUsername2() {
return username2;
}
public void setUsername2(String username2) {
this.username2 = username2;
}
}

@ -1,10 +1,22 @@
package org.example.objects;
import org.example.models.Category;
import org.springframework.web.multipart.MultipartFile;
public class PostDTO {
String title,content;
MultipartFile imageFile,videoFile;
Category category;
MultipartFile imageFile;
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
MultipartFile videoFile;
public String getTitle() {
return title;

@ -0,0 +1,39 @@
package org.example.objects;
import org.example.models.Image;
import org.example.models.Post;
import org.example.models.Video;
import org.springframework.data.neo4j.core.schema.Node;
import java.util.List;
public class PostWithMedia {
private Post post;
private List<Image> images;
private List<Video> videos;
// Getters and setters
public Post getPost() {
return post;
}
public void setPost(Post post) {
this.post = post;
}
public List<Image> getImages() {
return images;
}
public void setImages(List<Image> images) {
this.images = images;
}
public List<Video> getVideos() {
return videos;
}
public void setVideos(List<Video> videos) {
this.videos = videos;
}
}

@ -2,6 +2,8 @@ package org.example.repositories;
import org.example.models.Category;
import org.example.models.Post;
import org.example.objects.PostDTO;
import org.example.objects.PostWithMedia;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.data.repository.query.Param;
@ -11,6 +13,11 @@ import java.util.List;
@Repository
public interface CategoryRepository extends Neo4jRepository<Category, Long> {
@Query("MATCH (c:Category)-[:HAS_POST]->(p:Post) WHERE c.name IN $categoryNames RETURN p")
List<Post> findPostsByCategoryNames(@Param("categoryNames") List<String> categoryNames);
Category findByName(String name);
@Query("MATCH (c:Category)<-[:HAS_CATEGORY]-(p:Post)\n" +
"WHERE c.name = $categoryName\n" +
"OPTIONAL MATCH (p)-[:HAS_IMAGE]->(image:Image)\n" +
"OPTIONAL MATCH (p)-[:HAS_VIDEO]->(video:Video)\n" +
"RETURN ID(p)")
List<Long> findPostsByCategoryNames(@Param("categoryName") String categoryName);
}

@ -54,7 +54,7 @@ public interface PostRepository extends Neo4jRepository<Post,Long> {
"RETURN p")
Post likePost(@Param("username") String username, @Param("postId") Long postId);
@Query("MATCH (u:User)-[l:LIKES]->(p:Post) " +
@Query("MATCH (u:User)-[l:LIKED]->(p:Post) " +
"WHERE u.username=$username AND ID(p) = $postId " +
"DELETE l " +
"RETURN CASE WHEN COUNT(l) > 0 THEN true ELSE false END AS removed")
@ -70,19 +70,30 @@ public interface PostRepository extends Neo4jRepository<Post,Long> {
"RETURN p")
Post sharePost(@Param("username") String username, @Param("postId") Long postId);
@Query("MATCH (p:Post)\n" +
"OPTIONAL MATCH (p)-[:HAS_LIKE]->(l)\n" +
"OPTIONAL MATCH (p)-[:HAS_COMMENT]->(c)\n" +
"OPTIONAL MATCH (p)-[:HAS_SHARE]->(s)\n" +
@Query("MATCH (p:Post),(u:User)\n" +
"OPTIONAL MATCH (p)<-[l:LIKED]-(u)\n" +
"OPTIONAL MATCH (p)<-[c:COMMENTED]-(u)\n" +
"OPTIONAL MATCH (p)<-[s:SHARED]-(u)\n" +
"OPTIONAL MATCH (p)-[:HAS_IMAGE]->(image:Image)\n" +
"OPTIONAL MATCH (p)-[:HAS_VIDEO]->(video:Video)\n" +
"WITH p, COUNT(l) AS likeCount, COUNT(c) AS commentCount, COUNT(s) AS shareCount, COLLECT(DISTINCT image) AS images, COLLECT(DISTINCT video) AS videos\n" +
"WITH p, \n" +
" COUNT(DISTINCT l) AS likeCount, \n" +
" COUNT(DISTINCT c) AS commentCount, \n" +
" COUNT(DISTINCT s) AS shareCount, \n" +
" COLLECT(DISTINCT image) AS images, \n" +
" COLLECT(DISTINCT video) AS videos\n" +
"RETURN p, images, videos\n" +
"ORDER BY (likeCount + commentCount + shareCount) DESC\n" +
"LIMIT 10")
"LIMIT 10\n")
List<Post> findTop10ByInteractions();
@Query("MATCH (user:User {username: $username}),(post:Post )"+"where ID(post)=$postId"+ " CREATE (user)-[:createPost ]->(post)"+
"RETURN user, post")
PostQueryResult createPostRelationship(@Param("username") String username,@Param("postId") Long postId);
// @Query("match (p:Post)where id(p)=$postID\n" +
// "optional match (p)-[:HAS_IMAGE]->(image:Image)\n" +
// "optional match (p)-[:HAS_VIDEO]->(video:Video)\n" +
// "return p,image")
// List<Post> fi
}

@ -3,26 +3,51 @@ package org.example.repositories;
import org.example.models.Category;
import org.example.models.Post;
import org.example.models.User;
import org.example.objects.FriendDTO;
import org.example.queryresults.PostQueryResult;
import org.example.services.UserService;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
import java.util.Optional;
@Repository
public interface UserRepository extends Neo4jRepository<User, Long> {
Optional<User> findUserByUsername(String username);
boolean existsByUsername(String username);
@Query("MATCH (u:User)-[:FRIEND]->(f:User)-[:LIKED|COMMENTED|SHARED]->(p:Post) WHERE u.username=$username RETURN p")
List<Post> findFriendPosts(@Param("username") String username);
Optional<User> findUserByUsername(String username);
boolean existsByUsername(String username);
@Query("MATCH (u:User)-[:LIKED|COMMENTED|SHARED]->(p:Post)-[:HAS_POST]->(c:Category) WHERE u.username=$username RETURN DISTINCT c")
List<Category> findInteractedCategories(@Param("username") String username);
@Query("MATCH (u:User {name:$username1}), (f:User {name:$username2})\n" +
"OPTIONAL MATCH (u)-[fr:Friend]->(f), (f)-[fr1:Friend]->(u)\n" +
"WITH u, f, collect(fr) as friendships1, collect(fr1) as friendships2\n" +
"FOREACH (_ IN CASE WHEN size(friendships1) = 0 AND size(friendships2) = 0 THEN [1] ELSE [] END | \n" +
" CREATE (u)-[:Friend]->(f) \n" +
" CREATE (f)-[:Friend]->(u))\n" +
"FOREACH (_ IN CASE WHEN size(friendships1) > 0 AND size(friendships2) > 0 THEN [1] ELSE [] END | \n" +
" DELETE friendships1[0], friendships2[0])\n")
void addFriend(@Param("username1") String username1, @Param("username2") String username2);
@Query("MATCH (u:User {username:$username})-[:Friend]->(f:User)\n" +
"match (f)-[:createPost]->(p:Post)RETURN ID(p)")
List<Long> findFriendPosts(@Param("username") String username);
@Query("MATCH (u:User {username: $username})-[r:LIKED|COMMENTED|SHARED]->(p:Post)\n" +
"OPTIONAL MATCH (p)<-[like:LIKED]-(:User)\n" +
"OPTIONAL MATCH (p)<-[comment:COMMENTED]-(:User)\n" +
"OPTIONAL MATCH (p)<-[share:SHARED]-(:User)\n" +
"OPTIONAL MATCH (p)-[:HAS_CATEGORY]->(c:Category)\n" +
"WITH p, COUNT(DISTINCT like) AS likeCount, COUNT(DISTINCT comment) AS commentCount, COUNT(DISTINCT share) AS shareCount, c.name AS categories \n" +
"WHERE likeCount > 0 OR commentCount > 0 OR shareCount > 0\n" +
"RETURN categories \n" +
"ORDER BY (likeCount + commentCount + shareCount) DESC")
List<String> findInteractedCategories(@Param("username") String username);
}

@ -0,0 +1,23 @@
package org.example.services;
import org.example.models.Category;
import org.example.repositories.CategoryRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class CategoryService {
private final CategoryRepository categoryRepository;
public CategoryService(CategoryRepository categoryRepository) {
this.categoryRepository = categoryRepository;
}
public List<Category> getAllCategories() {
List<Category> categories = categoryRepository.findAll();
return categories;
}
}

@ -10,6 +10,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Service
public class InteractService {

@ -34,6 +34,7 @@ public class PostService {
private final UserService userService;
private final UserRepository userRepository;
private String username;
private Category category;
@Autowired
private Neo4jTemplate neo4jTemplate;
@ -62,11 +63,11 @@ public class PostService {
return getAllPost;
}
@Transactional
public Post createPost(String title, String content, MultipartFile imageFile, MultipartFile videoFile) throws IOException {
public Post createPost(String title, String content,Category category, MultipartFile imageFile, MultipartFile videoFile) throws IOException {
Post post = new Post();
post.setTitle(title);
post.setContent(content);
post.setCategory(category);
if (imageFile != null) {
Image image = saveImageFile(imageFile, "C:\\Users\\phucl\\OneDrive\\Desktop\\JAVA_INTER\\Facebook\\FE\\FE\\public\\picture");
// post.getImages().add(image);
@ -96,7 +97,7 @@ public class PostService {
}
}
@Transactional
public Post editPost(Long postId, String title, String content, MultipartFile imageFile, MultipartFile videoFile) throws IOException {
public Post editPost(Long postId, String title, String content,Category category, MultipartFile imageFile, MultipartFile videoFile) throws IOException {
Post post= postRepository.updatePost(postId,title,content,imageFile,videoFile);
// Update the image file if provided
if (imageFile != null) {

@ -3,6 +3,8 @@ package org.example.services;
import org.example.models.Category;
import org.example.models.Post;
import org.example.objects.PostDTO;
import org.example.objects.PostWithMedia;
import org.example.repositories.CategoryRepository;
import org.example.repositories.PostRepository;
import org.example.repositories.UserRepository;
@ -10,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
@ -28,11 +31,36 @@ public class RecommendationService {
public List<Post> getRecommendationPosts(String username) {
List<Post> recommendationPosts = new ArrayList<>();
recommendationPosts.addAll(postRepository.findTop10ByInteractions());
List<Category> categories = userRepository.findInteractedCategories(username);
List<String> categoriesNames = categories.stream().map(Category::getName).collect(Collectors.toList());
recommendationPosts.addAll(categoryRepository.findPostsByCategoryNames(categoriesNames));
recommendationPosts.addAll(userRepository.findFriendPosts(username));
//tim kiem bai viết phổ biến theo số lượng interact
List<Post> postsInteracts = new ArrayList<>();
postsInteracts=postRepository.findTop10ByInteractions();
for (Post post : postsInteracts) {
post.setImgUrl(postRepository.getImage(post.getId()));
recommendationPosts.add(post);
}
//tìm kiếm các bài post có chung chủ đề
List<String> categoriesNames = userRepository.findInteractedCategories(username);
for (String categoryName : categoriesNames) {
System.out.println(categoryName);
List<Long> IDposts = categoryRepository.findPostsByCategoryNames(categoryName);
for(Long IDpost : IDposts) {
System.out.println(IDpost);
Post post= postRepository.findById(IDpost).get();
if(!recommendationPosts.contains(post)) {
recommendationPosts.add(post);
post.setImgUrl(postRepository.getImage(IDpost));
}
}
}
List<Long> postsFriend;
postsFriend=userRepository.findFriendPosts(username);
for (Long postID : postsFriend) {
Post post = postRepository.findById(postID).get();
if(!recommendationPosts.contains(post)) {
post.setImgUrl(postRepository.getImage(post.getId()));
recommendationPosts.add(post);
}
}
return recommendationPosts.stream().distinct().collect(Collectors.toList());
}

@ -1,6 +1,7 @@
package org.example.services;
import org.example.models.User;
import org.example.repositories.PostRepository;
import org.example.repositories.UserRepository;
import org.example.requests.CreateUserRequest;
import org.springframework.security.crypto.password.PasswordEncoder;
@ -11,10 +12,12 @@ public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final PostRepository postRepository;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, PostRepository postRepository) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.postRepository = postRepository;
}
public User createUser(CreateUserRequest request) {
@ -33,4 +36,7 @@ public class UserService {
return user;
}
public void addFriend(String username1, String username2) {
userRepository.addFriend(username1,username2);
}
}

Loading…
Cancel
Save