在Django的Queryset中返回精确匹配的顶部结果

11 浏览
0 Comments

在Django的Queryset中返回精确匹配的顶部结果

我有一个Django模型,称为“用户”,它存储有关人们的一些基本信息,即名字和姓氏。目前,我在Django模型上进行了简单的搜索,如果用户输入名字,Django查询集将返回前10个匹配项,按姓氏排序。

例如,当前,如果搜索“Sam”,您可能会获得以下结果:

  1. Sam Abbott
  2. Samuel Baker
  3. Sammy Rogers
  4. Sam Simmons

这个代码很简单:

User.objects.filter(Q(first__istartswith=token)).order_by('last')

但是,我想将其改为首先返回精确的名字匹配,然后是其他结果。因此,如果有人输入“Sam”,结果应该如下:

  1. Sam Abbott
  2. Sam Simmons
  3. Samuel Baker
  4. Sammy Rogers

(首先是精确的名字匹配,按姓氏排序,然后是其他匹配项,按姓氏排序)。

我考虑将其转换为2个查询集,然后将列表组合起来,但我想知道是否有可能在1个查询中完成,最好使用基本的Django查询集API(而不是编写一次性查询)。有人知道如何做到这一点吗?

提前致谢。

admin 更改状态以发布 2023年5月22日
0
0 Comments

# 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个或多个查询集?

0
0 Comments

我不认为只用一个查询(至少使用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

0