fix: avoid duplicate rows in complex reverse queries

Add an optional distinct flag to complex query payload and deduplicate by primary key before annotate/order flow, so reverse-join filtering does not return repeated records.

Made-with: Cursor
This commit is contained in:
caoqianming 2026-03-13 16:35:12 +08:00
parent c99e74eee8
commit 4acd80718d
2 changed files with 7 additions and 0 deletions

View File

@ -252,6 +252,7 @@ class ComplexQueryMixin:
queryset = self.get_queryset() queryset = self.get_queryset()
querys = vdata.get('querys', []) querys = vdata.get('querys', [])
annotate_field_list = vdata.get('annotate_field_list', []) annotate_field_list = vdata.get('annotate_field_list', [])
distinct = vdata.get('distinct', True)
if not querys: if not querys:
new_qs = queryset new_qs = queryset
@ -275,6 +276,11 @@ class ComplexQueryMixin:
except Exception as e: except Exception as e:
raise ParseError(str(e)) raise ParseError(str(e))
# 反向关联(右到左)查询容易因 JOIN 膨胀产生重复行,这里按主键回查去重
if distinct:
pk_name = queryset.model._meta.pk.attname
new_qs = queryset.filter(**{f"{pk_name}__in": new_qs.values(pk_name)})
if annotate_field_list: if annotate_field_list:
annotate_dict = getattr(self, "annotate_dict", {}) annotate_dict = getattr(self, "annotate_dict", {})
if annotate_dict: if annotate_dict:

View File

@ -83,6 +83,7 @@ class ComplexSerializer(serializers.Serializer):
page = serializers.IntegerField(min_value=0, required=False) page = serializers.IntegerField(min_value=0, required=False)
page_size = serializers.IntegerField(min_value=1, required=False) page_size = serializers.IntegerField(min_value=1, required=False)
ordering = serializers.CharField(required=False) ordering = serializers.CharField(required=False)
distinct = serializers.BooleanField(required=False, default=True, label="是否按主键去重")
querys = serializers.ListField(child=QuerySerializer( querys = serializers.ListField(child=QuerySerializer(
many=True), label="查询列表", required=False) many=True), label="查询列表", required=False)
annotate_field_list = serializers.ListField(child=serializers.CharField(), label="RawSQL字段列表", required=False) annotate_field_list = serializers.ListField(child=serializers.CharField(), label="RawSQL字段列表", required=False)