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

如何按搜索词出现位置排序Django QuerySet实现菜单自动补全?

解决方案:按搜索词位置优先排序自动补全结果

要实现优先按搜索词在菜品名称中的出现位置排序,再按字母顺序排序的需求,你需要借助数据库的字符串位置计算函数,在Django中通过annotate添加临时排序字段,再基于该字段排序。

1. 选择对应数据库的位置计算函数

不同数据库的字符串位置函数不同,需根据你的数据库类型选择:

  • MySQL/MariaDB:使用CharIndex函数
  • PostgreSQL:使用StrPos函数
  • SQLite:使用Instr函数

2. 修改Django视图代码

以下是适配不同数据库的完整代码:

针对MySQL/MariaDB

from django.db.models import Value
from django.db.models.functions import CharIndex, Lower

def load_menu(request):
    term = request.GET['term']
    # 转小写以匹配icontains的大小写不敏感查询
    lower_term = Value(term.lower())
    menu = Menu.objects.filter(item__icontains=term)\
        .annotate(term_position=CharIndex(lower_term, Lower('item')))\
        .order_by('term_position', 'item', 'id')
    
    data = []
    for item in menu:
        data.append({
            'label': item.item,
            'value': item.id,
        })
    return JsonResponse({'data': data})

针对PostgreSQL

from django.db.models import Value
from django.db.models.functions import StrPos, Lower

def load_menu(request):
    term = request.GET['term']
    lower_term = Value(term.lower())
    menu = Menu.objects.filter(item__icontains=term)\
        .annotate(term_position=StrPos(Lower('item'), lower_term))\
        .order_by('term_position', 'item', 'id')
    
    data = []
    for item in menu:
        data.append({
            'label': item.item,
            'value': item.id,
        })
    return JsonResponse({'data': data})

针对SQLite

from django.db.models import Value
from django.db.models.functions import Instr, Lower

def load_menu(request):
    term = request.GET['term']
    lower_term = Value(term.lower())
    menu = Menu.objects.filter(item__icontains=term)\
        .annotate(term_position=Instr(Lower('item'), lower_term))\
        .order_by('term_position', 'item', 'id')
    
    data = []
    for item in menu:
        data.append({
            'label': item.item,
            'value': item.id,
        })
    return JsonResponse({'data': data})

代码说明

  • annotate(term_position=...):添加临时字段term_position,存储搜索词在菜品名称(转小写后)中的起始位置,位置数值越小代表搜索词出现得越靠前。
  • order_by('term_position', 'item', 'id'):先按term_position升序排序(优先展示搜索词出现位置靠前的结果),再按菜品名称字母序排序,最后按id排序保证结果的唯一性。
  • 转小写处理:保证大小写不敏感的查询和位置计算一致,避免因大小写差异导致排序错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:33:20