在Django的Queryset中返回精确匹配的顶部结果
在Django的Queryset中返回精确匹配的顶部结果
我有一个Django模型,称为“用户”,它存储有关人们的一些基本信息,即名字和姓氏。目前,我在Django模型上进行了简单的搜索,如果用户输入名字,Django查询集将返回前10个匹配项,按姓氏排序。
例如,当前,如果搜索“Sam”,您可能会获得以下结果:
- Sam Abbott
- Samuel Baker
- Sammy Rogers
- Sam Simmons
这个代码很简单:
User.objects.filter(Q(first__istartswith=token)).order_by('last')
但是,我想将其改为首先返回精确的名字匹配,然后是其他结果。因此,如果有人输入“Sam”,结果应该如下:
- Sam Abbott
- Sam Simmons
- Samuel Baker
- Sammy Rogers
(首先是精确的名字匹配,按姓氏排序,然后是其他匹配项,按姓氏排序)。
我考虑将其转换为2个查询集,然后将列表组合起来,但我想知道是否有可能在1个查询中完成,最好使用基本的Django查询集API(而不是编写一次性查询)。有人知道如何做到这一点吗?
提前致谢。
admin 更改状态以发布 2023年5月22日
# Get exact matches first qs1 = User.objects.filter(first__iexact=token).order_by('last') # get secondary results second qs2 = User.objects.filter(first__istartswith=token).exclude(qs1).order_by('last') result = itertools.chain(qs1, qs2)
还可以看看这个问题,它比你需要的更深入地涉及了: 如何在Django视图中合并2个或多个查询集?
我不认为只用一个查询(至少使用Django ORM)可以做到这一点。
因此,您的2个查询应该如下所示:
limit = 10 q1 = User.objects.filter(first__iexact=token).order_by('last')[:limit] limit -= len(q1) if limit: q2 = User.objects.exclude(pk__in=q1).filter(first__istartswith=token).order_by('last')[:limit] else: q2 = [] users = list(q1) + list(q2)
另一种方法是在python中过滤查询,但是您将不得不获取所有结果,而不仅仅是最后10个:
query = User.objects.filter(first__istartswith=token).order_by('last') exacts = [user for user in query if user.first == token] others = [user for user in query if user.first != token] users = exacts + others