Django оптимизация похожих запросов - PullRequest
0 голосов
/ 14 июля 2020

Проблема

Попытка оптимизировать аналогичный запрос

Случай

Скажем, у меня есть модель тега вакансии, например:

class VacancyTag(models.Model):
    TYPE_GENERAL = 1
    TYPE_EDUCATION_LEVEL = 2
    TYPE_LOCATION_CITY = 3
    TYPE_LOCATION_PROVINCE = 4
    TYPE_CONTRACT_TYPE = 5
    TYPE_JOB_TYPE = 6

    name = models.CharField(max_length=50)
    tag_type = models.SmallIntegerField(choices=(
        (TYPE_GENERAL, 'General'),
        (TYPE_EDUCATION_LEVEL, 'Education Level'),
        (TYPE_LOCATION_CITY, 'Location City'),
        (TYPE_LOCATION_PROVINCE, 'Location Province'),
        (TYPE_CONTRACT_TYPE, 'Contract Type'),
        (TYPE_JOB_TYPE, 'Job Type'),
    ), default=TYPE_GENERAL, db_index=True)

В представлении я разбираю несколько типов записей тегов в контексте следующим образом:

context['tag_education'] = vacancy_services.get_vacancy_tag_by_type(VacancyTag.TYPE_EDUCATION_LEVEL)
context['tag_job_type'] = vacancy_services.get_vacancy_tag_by_type(VacancyTag.TYPE_JOB_TYPE)
context['tag_contract_type'] = vacancy_services.get_vacancy_tag_by_type(VacancyTag.TYPE_CONTRACT_TYPE)

Где vacancy_services.get_vacancy_tag_by_type просто выполняю запрос следующим образом:

VacancyTag.objects.filter(tag_type=tag_type)

Используя Django Панель инструментов отладки, я заметил, что эти 3 контекста имеют похожий запрос, потому что он отличается только параметром фильтра tag_type.

Обыскивал его несколько раз и нашел ответ, предлагающий запросить все теги типа I нужно, а затем обработать данные в представлении, поэтому я попробовал что-то вроде этого:

        all_tags = vacancy_services.get_vacancy_tag_by_type_in([
            VacancyTag.TYPE_EDUCATION_LEVEL,
            VacancyTag.TYPE_JOB_TYPE,
            VacancyTag.TYPE_CONTRACT_TYPE,
        ])

        context['education_tags'] = [e for e in all_tags if e.tag_type == VacancyTag.TYPE_EDUCATION_LEVEL]

Где vacancy_services.get_vacancy_tag_by_type_in просто:

VacancyTag.objects.filter(tag_type__in=tag_types)

Однако он не оптимизировал запрос как Я хочу. Приведенный выше код приводит к двум различным запросам.

(0.006) SELECT "app_vacancy_vacancytag"."id", "app_vacancy_vacancytag"."name", "app_vacancy_vacancytag"."slug", "app_vacancy_vacancytag"."tag_type" FROM "app_vacancy_vacancytag" WHERE ("app_vacancy_vacancytag"."is_show" = 1 AND "app_vacancy_vacancytag"."tag_type" IN (2, 6, 5)) ORDER BY "app_vacancy_vacancytag"."tag_type" DESC, "app_vacancy_vacancytag"."is_popular" DESC, "app_vacancy_vacancytag"."hit_count" ASC LIMIT 21; args=(True, 2, 6, 5)
(0.000) SELECT "app_vacancy_vacancytag"."id", "app_vacancy_vacancytag"."name", "app_vacancy_vacancytag"."slug", "app_vacancy_vacancytag"."tag_type" FROM "app_vacancy_vacancytag" WHERE ("app_vacancy_vacancytag"."is_show" = 1 AND "app_vacancy_vacancytag"."tag_type" IN (2, 6, 5) AND "app_vacancy_vacancytag"."tag_type" = 2) ORDER BY "app_vacancy_vacancytag"."tag_type" DESC, "app_vacancy_vacancytag"."is_popular" DESC, "app_vacancy_vacancytag"."hit_count" ASC LIMIT 21; args=(True, 2, 6, 5, 2)

То, что я хочу

Приведенный выше код должен выполнять только 1 запрос (следовательно, оптимизацию) с возможностью получения и фильтрации нескольких типов тегов

Что я сделал не так? Где я пропустил?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...