如何按BigText出现频率对Django QuerySet进行排序?
解决方案
要实现按bigtext字段的出现频率降序排序(频率高的在前,同一bigtext的条目聚合在一起),可以通过Django ORM的窗口函数或子查询统计两种方式实现,以下是具体修改:
方法1:使用窗口函数(推荐,简洁高效,需数据库支持Window函数,如PostgreSQL、MySQL 8.0+)
修改get_queryset方法如下:
from django.db.models import Q, Count, Window, F from rest_framework import mixins, viewsets class BigTextKeywordViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet): queryset = BigTextKeyword.objects.all() serializer_class = BigTextKeywordSerializer def get_queryset(self): keyword_filter = Q() search_content = self.request.query_params.get('search_content', '') for term in search_content.split(' '): keyword_filter |= Q(keyword__icontains=term) keywords = Keyword.objects.filter(keyword_filter) # 核心修改:添加频率统计并排序 result = self.queryset.filter(keyword__in=keywords).annotate( # 窗口函数:统计当前bigtext在结果集中的出现次数 bigtext_frequency=Window( expression=Count('bigtext'), partition_by=F('bigtext_id') ) ).order_by('-bigtext_frequency', 'bigtext_id') return result
方法2:使用子查询统计(兼容旧版数据库,如MySQL 5.x)
如果你的数据库不支持Window函数,可改用子查询统计每个bigtext的出现次数:
from django.db.models import Q, Count, Subquery, OuterRef from rest_framework import mixins, viewsets class BigTextKeywordViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet): queryset = BigTextKeyword.objects.all() serializer_class = BigTextKeywordSerializer def get_queryset(self): keyword_filter = Q() search_content = self.request.query_params.get('search_content', '') for term in search_content.split(' '): keyword_filter |= Q(keyword__icontains=term) keywords = Keyword.objects.filter(keyword_filter) # 子查询:统计每个bigtext在结果集中的出现次数 count_subquery = BigTextKeyword.objects.filter( bigtext=OuterRef('bigtext'), keyword__in=keywords ).values('bigtext').annotate(count=Count('id')).values('count') # 核心修改:关联统计结果并排序 result = self.queryset.filter(keyword__in=keywords).annotate( bigtext_frequency=Subquery(count_subquery) ).order_by('-bigtext_frequency', 'bigtext_id') return result
说明
- 两种方法都会为每个
BigTextKeyword对象添加bigtext_frequency字段,表示该bigtext在查询结果中的出现次数。 - 排序规则:先按
bigtext_frequency降序(频率高的在前),再按bigtext_id排序(确保同一bigtext的条目聚合在一起)。 - 最终结果会和你给出的预期示例一致:同一
bigtext的所有条目连续排列,且出现次数多的bigtext组排在前面。
内容的提问来源于stack exchange,提问作者Mateus Alves de Oliveira
相关产品推荐
相关产品推荐

