Для создания сложных запросов лучше взаимодействовать с query_set как с Sets или использовать встроенные функции?
Я хочу написать сложный запрос, в котором требуется объединение и пересечение. Когда я проверил этот QA, я нашел два подхода. Таким образом, моя потребность может быть решена с помощью
needed_keys = [A, B, C]
qs1 = model.objects.filter(entity=needed_keys[0])
for entity in needed_keys:
qs1 = qs1 | model.objects.filter(entity=entity)
qs2 = qs2 & qs1
или
needed_keys = [A, B, C]
qs1 = model.objects.filter(entity=needed_keys[0])
for entity in needed_keys:
qs1 = qs1.union(model.objects.filter(entity=entity))
qs2 = qs2.intersection(qs1)
основываясь на одном из ответов , Кажется, что первый подход будет оценивать результат запросов и затем вычислять результат AND или OR на уровне питона, Хотя я не видел ничего об этой оценке в документах Django . Что именно произойдет?
Подводя итог, мои вопросы следующие: какой подход лучше? Действительно ли Django оценивает 'model.objects.filter(entity=entity)' каждый раз в цикле первого подхода?
P.S.
- пожалуйста, не обращайте внимания на имена переменных или структуру кода, целью было просто проиллюстрировать ситуацию.
- типом 'entity' является textField, поэтому я не могу использовать 'model.objects.filter(entity__in=needed_keys)'
- когда я проверил вывод 'q2.query', первый подход был более читабельным для меня, но я хочу быть уверенным в его производительности тоже.
На мой взгляд, оба варианта неверны. И это предложение тоже неверно:
тип 'entity' - textField, поэтому я не могу использовать 'model.objects.filter(entity__in=needed_keys)'
__in
работает и для строк. Вот почему:
needed_keys = Q(entity__in = ['Adidas', 'Basidas', 'Cididas'])
queryset = qs2.filter(entity__in=needed_keys)
больше здесь: https://docs.djangoproject.com/en/4.1/ref/models/querysets/#in
Следующий шаг, вы хотите отфильтровать qs2. Почему вы не делаете это напрямую вместо intersect:
qs2 = qs2.filter(pk__in = qs1.values_list('pk', flat=True))
Следующий шаг. Попробуйте начать работать с запросами в кверисетах, прежде чем просить их в БД, а не с данными в кверисетах.
Иначе вы потеряете время на создание obj
, которое вы выбросите при intersect:
query = Q(_connector=Q.OR, **{'entity':entity for entity in needed_keys})
qs2 = model.objects.filter(query_tocreate_qs2, query) # your intersection
Еще раз: если вы делаете intersect
для уже созданных объектов - вы загрязняете функцию time.