The problem with select que from Question que order by RAND() is that your DB will order all records before return one item. So it's expensive in large data sets.
A cheaper way to achieve this goal consist in two steps:
- Find total of records from where you will select one.
- Get one random item in this set.
To do that in MySql for example, you can do:
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, but to do that in spring data you need to create some native queries...
Fortunately, we can use pagination in order to resolve that. In your Repository Interface, create the methods (some repositories has this without need to define it):
Long count();
Page<Question> findAll(Pageable pageable);
And in your Service you can user your repository in the following way:
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;
}