9

私は「ユーザー」と呼ばれるdjangoモデルを持っています。これは、人に関する基本的な情報、つまり名前と名前を格納します。現在、djangoモデル全体を簡単に検索しています。ユーザーが名を入力すると、djangoクエリセットは最初の10件の一致を姓の順に返します。

たとえば、現在、「Sam」を検索すると、次の結果が得られる可能性があります。

  1. サムアボット
  2. サミュエル・ベイカー
  3. サミー・ロジャース
  4. サム・シモンズ

このためのコードは単純です:

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

ただし、これを変更して、完全な名の一致が最初に返され、その後に残りの結果が返されるようにします。したがって、誰かが「Sam」と入力した場合、結果は代わりに次のようになります。

  1. サムアボット
  2. サム・シモンズ
  3. サミュエル・ベイカー
  4. サミー・ロジャース

(完全な名が最初に一致し、名前で並べ替えられ、その後に残りの一致が名前で並べ替えられます)。

これを2つのクエリセットに変換してリストを結合することを考えましたが、1回限りのクエリを作成するのではなく、基本的なdjangoクエリセットAPIを使用して、1つのクエリでこれを実行できるかどうか疑問に思いました。誰かがそれをする方法を知っていますか?

前もって感謝します。

4

5 に答える 5

7

1 つのクエリ (少なくとも 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
于 2012-07-10T17:52:00.620 に答える
3
# 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つ以上のクエリセットを組み合わせる方法は?

于 2012-07-10T18:02:18.740 に答える
1

それを達成するには、実際に全文検索が必要になると思います。djang-sphinx をチェックしてください。

例が完全なユース ケースと同じくらい複雑な場合は、ユーザー コードで並べ替えと順序付けを処理するだけで済みます。

于 2012-07-10T05:56:04.017 に答える
0

複数の属性で注文できます。

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

したがって、最初に並べ替えるとfirst、オブジェクトは完全一致と後続の一致に従ってフィルターを取得します。そして、もう一度注文してlast、姓に従って並べ替えます。

于 2012-07-10T05:23:49.010 に答える