【问题标题】:Django 'in' statement unsupported on database [large scale]数据库不支持 Django 'in' 语句 [大规模]
【发布时间】:2014-02-11 17:55:33
【问题描述】:

我正在使用 Django,但收到一条错误消息,提示“此版本的 MySQL 尚不支持 'LIMIT & IN/ALL/ANY/SOME 子查询'”。

我的数据库结构大致如下:

    class ImageTag(models.Model):
        start_image = models.ForeignKey(Image)
        stop_image = models.ForeignKey(Image)
        tag = models.TextField(null=True)

    class Image(models.Model):
        [things we don't really care about right now]

我要做的是获取所有 ImageTag 对象的 start_image 字段中出现的唯一 Image 对象(注意:不是值,我需要实际对象)。我是怎么做的:

    tag_match = [filtering all tags based on a query]
    ids = tag_match.values('start_image').distinct()  #get the distinct image ids
    images = Image.objects.filter(id__in=ids)   #get the actual image objects

这是我能看到的最简单和最直接的方法来获取具有与之关联的 ImageTag 对象的唯一 Image 对象,但我的数据库后端不支持它。我已经看到了一些关于如何使用原始 SQL 解决此问题的建议,但如果可能的话,我真的很想避免这种情况,因为我们的开发设置和生产设置之间存在差异(为什么这首先是一个问题) 让我们很难知道什么实际可行,什么不可行。

对于这个问题的某种 Django 解决方法将不胜感激。

【问题讨论】:

  • 你用的是什么版本?另外,您使用的是什么版本的 Python?
  • 我们的服务器运行 MySQL 5.1.69 版本。我对 python 版本不太确定,但我相信它至少是 2.6。
  • 好的。你正在使用的 Django 的 version 怎么样?
  • 对其他任何技术一无所知,你能简单地在mysql中构建一个VIEW,然后从中选择吗?

标签: python mysql sql django


【解决方案1】:

问题来自 MySQL 本身,而不是 Python 或 Django - 你会在 PHP FWIW 中遇到同样的问题:MySQL - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery

Django 中的解决方法非常简单:传递一个普通列表,而不是 ValueQuerySet(这将导致 SQL 子查询),即:

tag_match = [filtering all tags based on a query]
ids = list(tag_match.values_list('start_image', flat=True).distinct())  
images = Image.objects.filter(id__in=ids)  

【讨论】:

  • 不幸的是,list() 操作符让我们的服务器上的 5 亿张图像无法扩展。
  • 那么使用一些真正的 SQL 数据库怎么样?比如说,PostgreSQL?
  • 我是一名在实验室工作的学生,所以我无法控制我们的服务器正在使用什么。我知道使用 PostgreSQL 会简单得多,但这不是解决我的问题的可行方案。
  • 其实我的时间评估错了。在这种情况下, list() 运算符将仅根据标签数量进行时间缩放,该数量远小于图像数量,这使得该答案有效。很抱歉我的困惑,谢谢你的回答!
【解决方案2】:

这是获取不同 Image 对象的另一种方法。请尝试并告知是否可行。

class ImageTag(models.Model):
    start_image = models.ForeignKey(Image, related_name="start_image_tags")
    stop_image = models.ForeignKey(Image)
    tag = models.TextField(null=True)

# Fetch only those Image objects which have a related ImageTag
images = Image.objects.exclude(start_image_tags=None).distinct()

# Fetch Image objects for filtered ImageTag query
tag_match = ImageTag.objects.filter(tag="any_filter")
images = Image.objects.filter(start_image_tags__in=tag_match).distinct()

【讨论】:

  • 这可以获取所有不同的图像,但是有没有办法获取与我的搜索匹配的 ImageTag 对象的过滤“tag_match”QuerySet 中的不同图像?
  • 添加了另一个过滤后的查询ImageTag。请立即尝试答案。
猜你喜欢
  • 2014-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
  • 2018-06-10
  • 2010-11-18
  • 2011-06-07
  • 2010-09-21
相关资源
最近更新 更多