Skip to content

Commit

Permalink
Merge pull request #128 from Lixuhuilll/Refactor-RatingUser
Browse files Browse the repository at this point in the history
重构评分系统
  • Loading branch information
dragove authored Aug 22, 2023
2 parents bc1a77a + c9ba18f commit 12f7dc8
Show file tree
Hide file tree
Showing 15 changed files with 537 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@ public interface CopilotConverter {
@Mapping(target = "uploaderId", ignore = true)
@Mapping(target = "uploadTime", ignore = true)
@Mapping(target = "firstUploadTime", ignore = true)
@Mapping(target = "likeCount", ignore = true)
@Mapping(target = "dislikeCount", ignore = true)
@Mapping(target = "ratingRatio", ignore = true)
@Mapping(target = "ratingLevel", ignore = true)
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void updateCopilotFromDto(CopilotDTO copilotDTO, String content, @MappingTarget Copilot copilot);

@Mapping(target = "id", ignore = true)
@Mapping(target = "deleteTime", ignore = true)
@Mapping(target = "likeCount", ignore = true)
@Mapping(target = "dislikeCount", ignore = true)
@Mapping(target = "ratingRatio", ignore = true)
@Mapping(target = "ratingLevel", ignore = true)
@Mapping(target = "views", constant = "0L")
@Mapping(target = "hotScore", constant = "0")
@Mapping(target = "delete", constant = "false")
Expand All @@ -53,6 +61,8 @@ public interface CopilotConverter {
@Mapping(target = "available", ignore = true)
@Mapping(target = "id", source = "copilotId")
@Mapping(target = "uploader", source = "userName")
@Mapping(target = "like", source = "copilot.likeCount")
@Mapping(target = "dislike", source = "copilot.dislikeCount")
@Mapping(target = "commentsCount", conditionExpression = "java(commentsCount != null)")
CopilotInfo toCopilotInfo(Copilot copilot, String userName, Long copilotId, Long commentsCount);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ public class CopilotInfo implements Serializable {
private int ratingType;
private long commentsCount;
private String content;
private long like;
private long dislike;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.util.Collection;
import java.util.List;
import java.util.Optional;

/**
* @author LoMu
Expand All @@ -14,8 +15,14 @@ public interface CopilotRatingRepository extends MongoRepository<CopilotRating,

CopilotRating findByCopilotId(Long copilotId);

Optional<CopilotRating> findByCopilotIdAndDelete(Long copilotId, boolean delete);

boolean existsCopilotRatingByCopilotId(Long copilotId);

boolean existsCopilotRatingByCopilotIdAndDelete(Long copilotId, boolean delete);

List<CopilotRating> findByCopilotIdIn(Collection<Long> copilotIds);

List<CopilotRating> findByCopilotIdInAndDelete(Collection<Long> copilotIds, boolean delete);

}
23 changes: 23 additions & 0 deletions src/main/java/plus/maa/backend/repository/RatingRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package plus.maa.backend.repository;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import plus.maa.backend.repository.entity.Rating;
import plus.maa.backend.service.model.RatingType;

import java.util.Optional;

/**
* @author lixuhuilll
* Date 2023-08-20 12:06
*/

@Repository
public interface RatingRepository extends MongoRepository<Rating, String> {
Optional<Rating> findByTypeAndKeyAndUserId(Rating.KeyType type, String key, String userId);

long countByTypeAndKeyAndRating(Rating.KeyType type, String key, RatingType rating);

long countByTypeAndKey(Rating.KeyType type, String key);
}

3 changes: 3 additions & 0 deletions src/main/java/plus/maa/backend/repository/RedisCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ public <T> void addSet(final String key, Collection<T> set, long timeout) {
}

public <T> void addSet(final String key, Collection<T> set, long timeout, TimeUnit timeUnit) {
if (key == null || set == null || set.isEmpty()) { // Redis 会拒绝空集合
return;
}
String[] jsonList = new String[set.size()];
try {
int i = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
Expand Down Expand Up @@ -36,7 +35,7 @@ public class CommentsArea implements Serializable {
private String message;

//赞 踩
private List<CopilotRating.RatingUser> ratingUser = new ArrayList<>();
private List<CopilotRating.RatingUser> ratingUser;

private long likeCount;

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/plus/maa/backend/repository/entity/Copilot.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ public class Copilot implements Serializable {
// 查看次数
private Long views = 0L;

//评级
private int ratingLevel;

//评级比率 十分之一代表半星
private double ratingRatio;

private long likeCount;

private long dislikeCount;

// 热度
private double hotScore;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package plus.maa.backend.repository.entity;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

import com.fasterxml.jackson.annotation.JsonIgnore;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

import java.time.LocalDateTime;
import java.util.List;

/**
* @author LoMu
Expand All @@ -31,7 +28,7 @@ public class CopilotRating {
@Indexed
private Long copilotId;
//评分用户
private List<RatingUser> ratingUsers = new ArrayList<>();
private List<RatingUser> ratingUsers;

//评级
private int ratingLevel;
Expand Down
49 changes: 49 additions & 0 deletions src/main/java/plus/maa/backend/repository/entity/Rating.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package plus.maa.backend.repository.entity;

import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.mapping.Document;
import plus.maa.backend.service.model.RatingType;

import java.time.LocalDateTime;

/**
* @author lixuhuilll
* Date 2023-08-20 11:20
*/

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "maa_rating")
// 复合索引
@CompoundIndexes({
// 一个用户对一个对象只能有一种评级
@CompoundIndex(name = "idx_rating", def = "{'type': 1, 'key': 1, 'userId': 1}", unique = true)
})
public class Rating {
@Id
private String id;

// 下面三个字段组成复合索引,一个用户对一个对象只能有一种评级
@NotNull
private KeyType type; // 评级的类型,如作业(copilot)、评论(comment)
@NotNull
private String key; // 被评级对象的唯一标识,如作业id、评论id
@NotNull
private String userId; // 评级的用户id

private RatingType rating; // 评级,如 "Like"、"Dislike"、"None"
private LocalDateTime rateTime; // 评级时间

public enum KeyType {
COPILOT, COMMENT
}
}
93 changes: 69 additions & 24 deletions src/main/java/plus/maa/backend/service/CommentsAreaService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@
import plus.maa.backend.controller.response.comments.SubCommentsInfo;
import plus.maa.backend.repository.CommentsAreaRepository;
import plus.maa.backend.repository.CopilotRepository;
import plus.maa.backend.repository.RatingRepository;
import plus.maa.backend.repository.UserRepository;
import plus.maa.backend.repository.entity.CommentsArea;
import plus.maa.backend.repository.entity.Copilot;
import plus.maa.backend.repository.entity.CopilotRating;
import plus.maa.backend.repository.entity.MaaUser;
import plus.maa.backend.repository.entity.*;
import plus.maa.backend.service.model.CommentNotification;
import plus.maa.backend.service.model.RatingType;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
Expand All @@ -41,6 +40,8 @@
public class CommentsAreaService {
private final CommentsAreaRepository commentsAreaRepository;

private final RatingRepository ratingRepository;

private final CopilotRepository copilotRepository;

private final UserRepository userRepository;
Expand Down Expand Up @@ -186,37 +187,81 @@ public void deleteComments(String userId, String commentsId) {
*/
public void rates(String userId, CommentsRatingDTO commentsRatingDTO) {
String rating = commentsRatingDTO.getRating();
boolean existRatingUser = false;

CommentsArea commentsArea = findCommentsById(commentsRatingDTO.getCommentId());
List<CopilotRating.RatingUser> ratingUserList = commentsArea.getRatingUser();

//判断是否存在 如果已存在则修改评分
for (CopilotRating.RatingUser ratingUser : ratingUserList) {
if (Objects.equals(userId, ratingUser.getUserId())) {
if (Objects.equals(rating, ratingUser.getRating())) {
return;
// 判断旧评分是否存在 如果存在则迁移评分
if (ratingUserList != null && !ratingUserList.isEmpty()) {
long likeCount = commentsArea.getLikeCount();
List<Rating> ratingList = new ArrayList<>();
for (CopilotRating.RatingUser ratingUser : ratingUserList) {

Rating newRating = new Rating()
.setType(Rating.KeyType.COMMENT)
.setKey(commentsArea.getId())
.setUserId(ratingUser.getUserId())
.setRating(RatingType.fromRatingType(ratingUser.getRating()))
.setRateTime(ratingUser.getRateTime());
ratingList.add(newRating);

if (Objects.equals(userId, ratingUser.getUserId())) {
if (Objects.equals(rating, ratingUser.getRating())) {
continue;
}
RatingType oldRatingType = newRating.getRating();
newRating.setRating(RatingType.fromRatingType(rating));
newRating.setRateTime(LocalDateTime.now());
likeCount += newRating.getRating() == RatingType.LIKE ? 1 :
(oldRatingType != RatingType.LIKE ? 0 : -1);
}
ratingUser.setRating(rating);
existRatingUser = true;
break;
}
if (likeCount < 0) {
likeCount = 0;
}
commentsArea.setLikeCount(likeCount);
commentsArea.setRatingUser(null);
ratingRepository.insert(ratingList);
commentsAreaRepository.save(commentsArea);
} // 迁移用代码结束,如不再需要可完全删除该 if 判断

long change;
Optional<Rating> ratingOptional = ratingRepository.findByTypeAndKeyAndUserId(Rating.KeyType.COMMENT, commentsArea.getId(), userId);
// 判断该用户是否存在评分
if (ratingOptional.isPresent()) {
// 如果评分发生变化则更新
if (!Objects.equals(ratingOptional.get().getRating(), RatingType.fromRatingType(rating))) {
RatingType oldRatingType = ratingOptional.get().getRating();
ratingOptional.get().setRating(RatingType.fromRatingType(rating));
ratingOptional.get().setRateTime(LocalDateTime.now());
RatingType newRatingType = ratingRepository.save(ratingOptional.get()).getRating();
// 更新评分后更新评论的点赞数
change = newRatingType == RatingType.LIKE ? 1 :
(oldRatingType != RatingType.LIKE ? 0 : -1);
} else {
// 如果评分未发生变化则结束
return;
}
} else {
// 不存在评分则创建
Rating newRating = new Rating()
.setType(Rating.KeyType.COMMENT)
.setKey(commentsArea.getId())
.setUserId(userId)
.setRating(RatingType.fromRatingType(rating))
.setRateTime(LocalDateTime.now());

ratingRepository.insert(newRating);
change = newRating.getRating() == RatingType.LIKE ? 1 : 0;
}

//不存在 创建一个用户评分
if (!existRatingUser) {
CopilotRating.RatingUser ratingUser = new CopilotRating.RatingUser(userId, rating, LocalDateTime.now());
ratingUserList.add(ratingUser);
// 点赞数不需要在高并发下特别精准,大概就行,但是也得避免特别离谱的数字
long likeCount = commentsArea.getLikeCount() + change;
if (likeCount < 0) {
likeCount = 0;
}

long likeCount = ratingUserList.stream()
.filter(ratingUser ->
Objects.equals(ratingUser.getRating(), "Like"))
.count();
commentsArea.setRatingUser(ratingUserList);
commentsArea.setLikeCount(likeCount);


commentsAreaRepository.save(commentsArea);
}

Expand Down
Loading

0 comments on commit 12f7dc8

Please sign in to comment.