Для создания сложных запросов лучше взаимодействовать с 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.

Вернуться на верх