Problem z select que from Question que order by RAND()
polega na tym, że twój DB zamawia wszystkie zapisy przed zwróceniem jednego przedmiotu. Jest więc drogi w dużych zbiorach danych.
Tańszy sposób, aby osiągnąć ten cel składa się w dwóch etapach:
- Find sumie zapisów skąd można wybrać jedną.
- Zdobądź losowy przedmiot w tym zestawie.
Aby to zrobić w MySQL, na przykład, można zrobić:
select count(*) from question;
// using any programming language, choose a random number between 0 and count-1 (let's save this number in rdn), and finally
select * from question LIMIT $rdn, 1;
Ok, ale aby to zrobić w danych sprężyny trzeba utworzyć kilka rodzimych zapytań ...
szczęście możemy użyć podziału na strony, aby to rozwiązać. W repozytorium interfejsu, tworzenie metod (niektóre repozytoria ma to bez konieczności jej określić):
Long count();
Page<Question> findAll(Pageable pageable);
I w usłudze możesz użytkownik repozytorium w następujący sposób:
public Question randomQuestion() {
Long qty = questionRepository.countAll();
int idx = (int)(Math.random() * qty);
Page<Question> questionPage = questionRepository.findAll(new PageRequest(idx, 1));
Question q = null;
if (questionPage.hasContent()) {
q = questionPage.getContent().get(0);
}
return q;
}
Jest to jeden tych doskonałych odpowiedzi, gdzie (a) to jest dokładnie to, czego potrzebowałem i (b) Google i ja nie byliśmy w stanie znaleźć niczego innego, co mogłoby zamknąć się zdalnie. Ale myślę, że masz literówkę: nie powinien "countAll()" być "count()"? – fivedogit