如何有效地获取已过滤查询集的随机元素



我尝试以这种方式从已经过滤的查询集中提取一个随机对象:

Product.objects.filter(active=True).order_by('?').first()

目前它是用.order_by('?')解决的,但似乎很慢。

我试图按照我的观点来解决这个问题。

它不起作用,所以我不确定我做这件事的方式是否正确。

products = Product.objects.filter(
active=True,
)
count = products.aggregate(count=Count('id'))['count']
random_index = randint(0, count - 1)
product = products[random_index]

这是我现在的代码,它抛出ValueError:

ValueError: low >= high

请帮我加快速度。

如果.order_by('?')太慢,一个不错的选择(取决于产品数量(可能是查询项目的PKs,然后随机选择一个:

qs = Product.objects.filter(active=True)
pks = list(qs.values_list('id', flat=True))
random_pk = random.choice(active_product_pks)
random_item = qs.get(pk=random_pk)

如果符合您的业务需求,您也可以在Django缓存中缓存pks一段时间。

您可以这样做:

import random
products = Product.objects.filter(
active=True,
)
items = list(products)
# if you want only a single random item
random_item = random.choice(items)  

或者这个:

from random import randint
count = Product.objects.count()
try:
random_choice = randint(0, count - 1)
except:
# if count == 0 then it will raise a ValueError.
random_choice = 0  
random_object = Product.objects.none()
if random_choice > 0:
random_object = Product.objects.all()[random_choice]  

p.s1:第二种解决方案更有效
P.s2:不要使用order_by('?')

最新更新