Оценка объекта на основе количества лайков и времени создания - PullRequest
0 голосов
/ 18 сентября 2018

При чтении из базы данных я хочу отсортировать свои 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;
}

Работает нормально, но может быть не лучшим подходом, потому что:

  1. Я думаю, что СУБД не может создать индекс для атрибута score.
  2. Жестко закодированная функция UNIX_TIMESTAMP() специфична для MySQL.Так что это вызовет проблемы, если я захочу использовать другую базу данных (скажем, H2) в моей тестовой среде.

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Используйте триггеры базы данных для обновления / обслуживания этих таблиц боковых агрегатов.Выполнять тяжелые запланированные задания для таких вещей (которые вызывают скачки нагрузки) действительно не имеет смысла ...

Кроме того, ниже условия WHERE никогда не будут использоваться индексы.Никогда и никогда.

UNIX_TIMESTAMP(creation_date_time) / 24 * 60 * 60 * 1000 + likes_count
0 голосов
/ 21 октября 2018

Я думаю о решении, которое может быть интересным и поможет вам поддерживать ваш счет в актуальном состоянии.Было бы создать планировщик, который будет каждые определенное количество времени (для моего примера, это будет выполняться ежедневно в 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);
        }

    }

}

Для того, чтобы запланированные задачи работали, вы должны добавить следующую аннотацию в свой Основной класс, @EnableScheduling.Конечно, это будет работать на всех СУБД, поэтому вам не нужно беспокоиться о том, какую БД вы используете, и у вас будет постоянно обновленный индекс.

Рекомендации

  • Это должно быть сделано партиями, чтобы он работал намного лучше.
  • Я бы, конечно, разбил на страницы мой метод getPost(), так что я мог бы получить только правдоподобную суммуобновлять каждый цикл.
  • Кроме того, я бы установил максимальную дату для получения сообщений.В любом случае, через некоторое время сообщение может быть неактуальным.
...