You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django Rest中按搜索字符串匹配位置排序查询结果?

基于搜索字符串匹配位置排序Django Rest框架搜索结果

可以实现,核心思路是通过给查询集添加排序注解,区分「以搜索串开头」和「搜索串在中间」的结果,再按匹配位置排序。

实现步骤

  1. 筛选出包含搜索字符串的结果
  2. 给查询集添加两个注解:
    • starts_with:标记结果是否以搜索串开头(1为是,0为否),用于优先展示开头匹配的内容
    • match_position:获取搜索串在字段中的起始位置,用于同类型结果内按匹配位置排序
  3. 按注解字段排序,先按starts_with降序,再按match_position升序

代码示例

假设你的模型为MyModel,需要搜索的字段是name,在视图集中实现如下:

from django.db.models import Case, When, Value, IntegerField
from django.db.models.functions import StrIndex
from rest_framework import viewsets

class MyModelViewSet(viewsets.ModelViewSet):
    serializer_class = MyModelSerializer
    queryset = MyModel.objects.all()

    def get_queryset(self):
        queryset = super().get_queryset()
        search_str = self.request.query_params.get('search', '')
        
        if search_str:
            # 筛选包含搜索字符串的记录
            queryset = queryset.filter(name__icontains=search_str)
            # 添加排序注解
            queryset = queryset.annotate(
                starts_with=Case(
                    When(name__istartswith=search_str, then=Value(1)),
                    default=Value(0),
                    output_field=IntegerField()
                ),
                match_position=StrIndex('name', Value(search_str))
            )
            # 按优先级排序:开头匹配的在前,同优先级下匹配位置越靠前越前
            queryset = queryset.order_by('-starts_with', 'match_position')
        
        return queryset

效果说明

针对你给出的示例:

  • 原始匹配结果:["another test", "test", "teeest"]
  • 排序后:["test", "teeest", "another test"]
    • test和teeest以te开头,starts_with=1,排在前面;两者的match_position都是1,顺序保持原查询集顺序(或可根据需求调整)
    • another test的starts_with=0,match_position=8,排在最后

如果需要区分大小写搜索,将icontains改为contains,istartswith改为startswith即可。

内容的提问来源于stack exchange,提问作者sadat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 09:20:30