Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django, fast way for random record with aggregates

So I have the following query:

Person.objects.annotate(film_count=Count('film')).filter(film_count__gte=3).order_by('?')[0]

Which pulls a random person that has 3 films or more. However, as stated in the django documents (https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by-fields) this approach with the ('?') is very slow and I plan for this query to be used frequently by users.

I suppose one way to do it is to fetch all the primary keys generated by the full list of that query, and then store it in a txt file and randomly select one each time. But I'm wondering if there is a more elegant solution?

I guess another way is to do:

Person.objects.annotate(film_count=Count('film')).filter(film_count__gte=3).get(pk=randint(1,num_persons))

where num_persons is the number of people in my database, and if the person does not match the query and throws a DoesNotExist error I simply run it again.

like image 241
dl8 Avatar asked Jan 26 '26 11:01

dl8


1 Answers

You can use the simplest solution: count the rows and select one at random:

queryset = Person.objects.annotate(film_count=Count('film')).filter(film_count__gte=3)
count = queryset.count()
result = queryset[random.randint(count)]

Note, however, that this approach might fail if some rows are deleted before lines 2 and 3 of the snippet (so you might wrap last line in a try-catch with retry)

like image 187
Wojciech Ptak Avatar answered Jan 29 '26 02:01

Wojciech Ptak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!