3

所以我有以下查询:

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

这会拉出一个拥有 3 部电影或更多电影的随机人。但是,正如 django 文档(https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by-fields)中所述,这种带有('?')的方法非常慢,我计划让用户经常使用此查询。

我想一种方法是获取由该查询的完整列表生成的所有主键,然后将其存储在一个 txt 文件中并每次随机选择一个。但我想知道是否有更优雅的解决方案?

我想另一种方法是:

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

其中 num_persons 是我的数据库中的人数,如果此人与查询不匹配并引发DoesNotExist错误,我只需再次运行它。

4

3 回答 3

1

您可以使用最简单的解决方案:计算行数并随机选择一个:

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

但是请注意,如果在片段的第 2 行和第 3 行之前删除了某些行,则此方法可能会失败(因此您可以将最后一行包装在 try-catch 中并重试)

于 2013-10-19T17:12:37.923 回答
0

就像我在帖子中编辑的那样,我可以这样做:

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

在 try/except 块中,如果记录不存在,只需使用不同的随机数再试一次。

于 2013-10-19T10:42:28.603 回答
0

如果您在 ORM 中指定随机运算符,我很确定它会给您两个不同的随机结果,不是吗?

MyModel.objects.order_by('?')[:2] # 2 random results.

Note: order_by('?') queries may be expensive and slow, depending on the database backend you’re using.
于 2014-01-24T06:15:18.100 回答