计算两个 Django 查询的交集:一个聚合,另一个 - 简单
Calculate intersection of two Django queries: one aggregate, another - simple
我有一个模型 VariantTag
,它存储另一个名为 SavedVariant
的模型的 ids
。前者有另一个 variant_tag_type_id
指向它的相对模型类型 VariantTagType
。现在我正在尝试获取所有具有 only one
variant_tag_type.name = 'Review'
标签的 SavedVariant
ids
。为了让事情更清楚,这是我在 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: each INTERSECT query must have the same number of columns
LINE 1: ...nttag"."saved_variant_id") = 1) INTERSECT (SELECT "seqr_vari...
如何在 Django
中编写这样的查询?
Update
我使用了 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: Merging 'QuerySet' classes must involve the same values in each case.
Update
我改了第二个空栏的名字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
并计算它们的交集,但我想避免在最后一点之前查询数据库。
最初,您用 id_count
注释了第一个查询,这意味着它将成为查询结果中的一列,第二个查询中不存在该列,您可能只想注释它作为 Value(0) 在相交时保持列一致。
完成后,您现在可以尝试在交叉路口进行初始尝试,或者您可以尝试此过滤器:
single_variant_ids.filter(saved_variant_id__in=review_all_variant_ids.values_list('saved_variant_id'))
祝一切顺利
我有一个模型 VariantTag
,它存储另一个名为 SavedVariant
的模型的 ids
。前者有另一个 variant_tag_type_id
指向它的相对模型类型 VariantTagType
。现在我正在尝试获取所有具有 only one
variant_tag_type.name = 'Review'
标签的 SavedVariant
ids
。为了让事情更清楚,这是我在 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: each INTERSECT query must have the same number of columns LINE 1: ...nttag"."saved_variant_id") = 1) INTERSECT (SELECT "seqr_vari...
如何在 Django
中编写这样的查询?
Update
我使用了 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: Merging 'QuerySet' classes must involve the same values in each case.
Update
我改了第二个空栏的名字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
并计算它们的交集,但我想避免在最后一点之前查询数据库。
最初,您用 id_count
注释了第一个查询,这意味着它将成为查询结果中的一列,第二个查询中不存在该列,您可能只想注释它作为 Value(0) 在相交时保持列一致。
完成后,您现在可以尝试在交叉路口进行初始尝试,或者您可以尝试此过滤器:
single_variant_ids.filter(saved_variant_id__in=review_all_variant_ids.values_list('saved_variant_id'))
祝一切顺利