根据其喜欢计数和创建时间对实体进行评分

Mah*_*zad 6 java database spring hibernate calculated-columns

从数据库读取时,我想Post基于两个因素对我的实体进行排序:

  • 喜欢数(越多越好)
  • 年龄(越新越好)

目前我已经这样实现了(作为计算值):

@Entity
public class Post {

    // divide timestamp by a day length so after each day score decrements by 1
    @Formula("UNIX_TIMESTAMP(creation_date_time) / 24 * 60 * 60 * 1000 + likes_count")
    private long score;

    @CreationTimestamp
    private LocalDateTime creationDateTime;

    @Min(0)
    private long likesCount;
}
Run Code Online (Sandbox Code Playgroud)

它工作正常但可能不是最好的方法,因为:

  1. 我认为RDBMS不能为score属性创建任何索引.
  2. 硬编码功能UNIX_TIMESTAMP()特定于MySQL.因此,如果我想在我的测试环境中使用另一个数据库(比如H2),这将导致问题.

Ala*_*ruz 1

我想到了一个可能很有趣并且可以帮助您保持分数更新的解决方案。将创建一个调度程序,每隔一定的时间(对于我的示例,它将在每天凌晨 1 点完成),将检查所有更新其分数的帖子,以这种方式维护更新的分数。

@Component
public class Scheduler {

    @Autowired
    PostService postService;

    // Dialy routine that will start at 1:00 am.
    @Scheduled(cron="0 0 1 * * *")
    public void updateDateScore() {

        // Of course, I wouldn't recommend doing this all at once.
        // I would do it in batches, but this is just to give you an idea.
        List<Post> posts = postService.getAll();
        for(Post p: posts) {
           LocalDateTime time = p.getCreationTime();
           ZoneId zoneId = ZoneId.systemDefault(); 
           long epoch = time.atZone(zoneId).toEpochSecond();
           // Your formula.
           long score = epoch / 24 * 60 * 60 * 1000 + p.getLikesCount();
           p.setScore(score);
           postService.update(p);
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

为了使计划任务正常工作,您必须将以下注释添加到您的 Main 类中@EnableScheduling。当然,这适用于所有 RDBMS,因此您无需担心您正在使用什么数据库,并且您将始终拥有更新的索引。

建议

  • 这应该分批完成,这样效果会更好。
  • 我当然会对我的getPost()方法进行分页,这样我只会获取合理的数量来更新每个循环。
  • 另外,我会设置获取帖子的最大日期。无论如何,经过一定时间后,帖子可能不再那么相关。