从多对多关系返回一组随机排序的不同对象

发布于 2024-12-02 11:45:29 字数 1177 浏览 0 评论 0原文

我正在使用 Django 1.3 和 Postgresql 8.4,并且我得到了如下所示的模型(删除了不相关的内容):

class Service(models.Model):
    name = models.CharField(max_length=80)

class Location(models.Model):
    name = models.CharField(max_length=80)
    services = models.ManyToManyField(Service, through='LocalService')

class LocalService(models.Model):
    location = models.ForeignKey(Location)
    service = models.ForeignKey(Service)

我试图获取一组不同的 Service 对象,按链接的 Location 对象的属性进行过滤,并随机排序。我首先尝试了这个:

Service.objects.filter(location__name__icontains='o').distinct().order_by('?')

...但这引发了这个异常:

数据库错误:对于 SELECT DISTINCT,必须出现 ORDER BY 表达式 在选择列表中

谷歌搜索后,我发现要在 SQL 级别实现这种结果,需要将 DISTINCT 和 ORDER BY 放在单独的查询级别中,即:使用子查询。如果我子查询一组不同的结果,我可以像这样随机排序它们:

SELECT * 
FROM (
    SELECT DISTINCT s.*
    FROM profile_service s
    JOIN profile_localservice ls
    ON ls.service_id = s.id
    JOIN profile_location l
    ON ls.location_id = l.id
    WHERE l.name LIKE '%o%'
) as temptable
ORDER BY RANDOM()

我是否需要使用 Manager.raw() 方法与此 SQL 查询来获取我的模型实例集,或者是否有更简单的方法来执行此操作在 Django API 中?

I'm using Django 1.3 with Postgresql 8.4 and I've got models like the following (irrelevant stuff removed):

class Service(models.Model):
    name = models.CharField(max_length=80)

class Location(models.Model):
    name = models.CharField(max_length=80)
    services = models.ManyToManyField(Service, through='LocalService')

class LocalService(models.Model):
    location = models.ForeignKey(Location)
    service = models.ForeignKey(Service)

I'm trying to get a distinct set of Service objects, filtered by attributes of linked Location objects, and ordered randomly. I tried this first:

Service.objects.filter(location__name__icontains='o').distinct().order_by('?')

...but that throws this exception:

DatabaseError: for SELECT DISTINCT, ORDER BY expressions must appear
in select list

After Googling around, I discovered that to achieve this kind of result at the SQL level, you need to put the DISTINCT and the ORDER BY in separate query levels, ie: use a subquery. If I subquery a DISTINCT set of results I can randomly order them like this:

SELECT * 
FROM (
    SELECT DISTINCT s.*
    FROM profile_service s
    JOIN profile_localservice ls
    ON ls.service_id = s.id
    JOIN profile_location l
    ON ls.location_id = l.id
    WHERE l.name LIKE '%o%'
) as temptable
ORDER BY RANDOM()

Do I need to use the Manager.raw() method with this SQL query to get my set of model instances, or is there a simpler way to do this from within the Django API?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

耳根太软 2024-12-09 11:45:29

根据您的具体要求,以下内容可能会起作用(并且可能比 ORDER BY Random() 表现更好)。我不确定 Postgresql,但是对于 MySQL,除了小数据集之外的任何东西的随机排序都非常慢。

services = list(Service.objects.filter(location__name__icontains='o').distinct())
random.shuffle(services)

Depending on your exact requirements the following might work (and potentially perform better than ORDER BY Random()). I'm not sure about Postgresql, but with MySQL randomized ordering on anything but a tiny dataset is really slow.

services = list(Service.objects.filter(location__name__icontains='o').distinct())
random.shuffle(services)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文