简体   繁体   English

将 django RawQuerySet 转换为 Queryset

[英]Convert django RawQuerySet to Queryset

I have 2 Django models, ModelA with an ArrayField that is used to store a large list of primary key values (possibly 50k+ list)我有 2 个 Django 模型, ModelA带有一个ArrayField ,用于存储主键值的大列表(可能是 50k+ 列表)

class ModelA(models.Model):
    pk_values = ArrayField(models.IntegerField())

class CustomManager(manager.Manager):

    def get_for_index(self, index_id):
        qs = self.get_queryset()
        obj = ModelA.objects.get(pk=index_id)
        return qs.filter(id__in=obj.pk_values)

class ModelB(models.Model):
    # [...] some fields

    objects = CustomManager()

This works:这有效:

qs = ModelB.objects.get_for_index(index_id=1)

However, this would be super slow where "pk_values" is a large list.但是,在“pk_values”是一个大列表的情况下,这将非常慢。

So I tried doing raw SQL queries:所以我尝试做原始 SQL 查询:

class CustomManager(manager.Manager):
    def get_for_index(self, index_id):
        qs = self.get_queryset()
        sql = "SELECT * FROM myapp_model_b JOIN myapp_model_a ON myapp_model_b.id = ANY(myapp_model_a.pk_values) WHERE myapp_model_a.id = '%s'" % index_id
        return qs.raw(sql)

But this returns a django.db.models.query.RawQuerySet instance.但这会返回一个django.db.models.query.RawQuerySet实例。

But with this, I cant do things like queryset.values() afterwards.但是有了这个,我之后就不能做queryset.values()类的事情了。

How can I convert this to a normal Django queryset?如何将其转换为普通的 Django 查询集?

Is there a better way of doing this?有没有更好的方法来做到这一点?

Docs:文档:

You can use a RawSQL expression:您可以使用RawSQL表达式:

ModelB.objects.filter(id__in=RawSQL(
    'SELECT unnest(a.pk_values) FROM app_modela a WHERE a.id = %s',
    [index_id]
))

Alternatively you can reproduce the exact query you have in your question with extra() :或者,您可以使用extra()重现您在问题中的确切查询:

ModelB.objects.extra(
    tables=['foo_modela'],
    where=[
        '"app_modelb"."id" = ANY("app_modela"."pk_values")',
        '"app_modela"."id" = %s',
    ],
    params=[index_id],
)

Update: I got something working using .extra()更新:我使用.extra()得到了一些工作

class CustomManager(manager.Manager):
    def get_for_index(self, index_id):
        qs = self.get_queryset()
        sql = "myapp_model_b.id IN (SELECT UNNEST(myapp_model_a.pk_values) FROM myapp_model_a WHERE myapp_model_a.id='%s')" % index_id
        return qs.extra(where=[sql])

Docs: https://docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.query.QuerySet.extra文档: https : //docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.query.QuerySet.extra

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM