Рассчитать пересечение двух Django запросов: один агрегат, другой - простой - PullRequest
0 голосов
/ 28 января 2020

У меня есть модель VariantTag, в которой хранится ids другой модели с именем SavedVariant. У первого есть variant_tag_type_id, который указывает на относительный тип модели VariantTagType. Сейчас я пытаюсь получить все SavedVariant ids, которые имеют тег only one variant_tag_type.name = 'Review'. Чтобы прояснить ситуацию, вот что я пытаюсь сделать в Django:

    # Variants with just only one tag present                                                                          
    single_variant_ids = VariantTag.objects.values_list('saved_variant_id', flat=True) \                               
            .annotate(id_count=Count('saved_variant_id')).filter(id_count=1)                                           
    # All variants that have 'Review' tag                                                                              
    review_all_variant_ids = VariantTag.objects.filter(variant_tag_type__name='Review') \                              
            .values_list('saved_variant_id', flat=True)                                                                
    # Intersection of the previous two queries                                                                         
    review_variant_ids = single_variant_ids.intersection(review_all_variant_ids)

И это не работает, выдавая ошибку:

ProgrammingError: каждый запрос INTERSECT должно иметь одинаковое количество столбцов LINE 1: ... nttag "." save_variant_id ") = 1) INTERSECT (SELECT" seqr_vari ...

Как мне написать такой запрос в Django?

Обновление

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

review_all_variant_ids = VariantTag.objects.filter(variant_tag_type__name='Review') \                              
                .values_list('saved_variant_id', flat=True).annotate(val=Value(0, output_field=IntegerField()))  

Однако intersection неправильно вычисляет пересечение, а просто возвращает пустое QuerySet. Я проверил оба QuerySets, преобразовав их в python lists и распечатав их, и вот что я вижу:

single_variant_ids: [46, 28, 38, 30, 33, 29, 47, 31, 44]
review_all_variant_ids: [22, 36, 46, 47]
review_variant_ids: []

Как видите, результат пересечения не должен быть пустым, а должен быть QuerySet со значениями: 46 и 47. Я также пытался просто написать пересечение следующим образом:

single_variant_ids & review_all_variant_ids 

Но выдает ошибку:

TypeError: Merg Классы 'QuerySet' должны содержать одинаковые значения в каждом случае.

Обновление

Я изменил имя пустого столбца второго QuerySet:

review_all_variant_ids = VariantTag.objects.filter(variant_tag_type__name='Review') \                              
                .values_list('saved_variant_id', flat=True).annotate(id_count=Value(0, output_field=IntegerField()))

После чего сработало следующее:

review_variant_ids = single_variant_ids & review_all_variant_ids

Но результат неправильный:

[22, 36, 46, 47]

Итак, пересечение здесь выполняется не так, как мне нужно , Конечно, проще всего просто преобразовать оба QuerySets в python sets и вычислить их пересечение, но я хочу избежать запросов к базе данных до самой последней точки.

1 Ответ

1 голос
/ 02 февраля 2020

Первоначально вы аннотировали первый запрос с помощью id_count, что означает, что он будет столбцом в результате запроса, этот столбец не существует во втором запросе, вы можете просто добавить его в качестве значения (0), чтобы столбцы оставались непротиворечивыми при пересечении.

После того, как вы это сделали, вы можете попробовать первоначальную попытку пересечения или этот фильтр:

single_variant_ids.filter(saved_variant_id__in=review_all_variant_ids.values_list('saved_variant_id'))

Все лучший

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