ページ付け

アプリケーションが非常に多数の結果を処理することは、多くの場合非現実的です。このため、API と Web サービスではページ区切りコントロールを使用して、アプリケーションが結果を小さなチャンクまたはページで要求できるようにします。

デフォルトでは、Elasticsearch は 10 件を超える結果を返さないことに気付いたかもしれません。オプションのsizeパラメータを検索リクエストに指定すると、この最大値を変更できます。次の例では、最大 5 件の検索結果を返すように要求しています。

results = es.search(
    query={
        'multi_match': {
            'query': query,
            'fields': ['name', 'summary', 'content'],
        }
    }, size=5
)

結果の追加ページにアクセスするには、 from_パラメータを使用します。これは、完全な結果リストのどこから開始するかを示します ( fromは Python の予約キーワードであるため、 from_が使用されます)。

次の例では、2 ページ目の 5 件の結果を取得します。

results = es.search(
    query={
        'multi_match': {
            'query': query,
            'fields': ['name', 'summary', 'content'],
        }
    }, size=5, from_=5
)

app.pyhandle_search()エンドポイントにsizefrom_を組み込みましょう。

@app.post('/')
def handle_search():
    query = request.form.get('query', '')
    from_ = request.form.get('from_', type=int, default=0)
    results = es.search(
        query={
            'multi_match': {
                'query': query,
                'fields': ['name', 'summary', 'content'],
            }
        }, size=5, from_=from_
    )
    return render_template('index.html', results=results['hits']['hits'],
                           query=query, from_=from_,
                           total=results['hits']['total']['value'])

ここで、ページ サイズは 5 にハードコードされています (任意の他の数値を自由に使用できます)。from_引数は、送信されたフォームの追加フィールドとして指定されると想定されていますが、このフィールドはオプションと見なされ、存在しない場合はデフォルトで 0 になります。

index.htmlで使用できる検索フォームにはfrom_フィールドがないため、通常の検索は常に最初の結果から開始されます。テンプレートには、表示される結果の範囲と合計に関する情報が表示されます。テンプレート式を使用してこれを実行する方法は次のとおりです。

<div class="col-sm-auto my-auto">
    Showing results {{ from_ + 1 }}-{{ from_ + results|length }} out of {{ total }}.
</div>

テンプレートには、結果リスト内を前方または後方に移動するためのページ区切りボタンを表示するロジックも含まれています。「前の結果」ボタンの実装は次のとおりです。

{% if from_ > 0 %}
    <div class="col-sm-auto my-auto">
        <a href="javascript:history.back(1)" class="btn btn-primary">← Previous page</a>
    </div> 
{% endif %}

ご覧のとおり、「前のページ」ボタンは、 from_が 0 より大きい場合にのみページにレンダリングされます。このボタンの実装では、ブラウザの履歴 API を使用して 1 ページ戻ります。

「次のページ」ボタンの実装はさらに興味深いものになっています。

{% if from_ + results|length < total %}
    <div class="col-sm-auto my-auto">
        <form method="POST">
            <input type="hidden" name="query" value="{{ query }}">
            <input type="hidden" name="from_" value="{{ from_ + results|length }}">
            <button type="submit" class="btn btn-primary">Next page →</button>
        </form>
    </div>
{% endif %}

このボタンは実際にはスタンドアロンのボタンではなく、ボタンに加えて 2 つの隠しフィールドを持つ完全なフォームです。このフォームはメインの検索フォームに似ていますが、次の結果ページを指すように調整されたオプションのfrom_フィールドが含まれています。このボタンをクリックすると、Flask アプリケーションはこの代替フォームからの検索要求を受け取ります。この要求では、同じテキスト クエリが使用されますが、値はゼロ以外のfrom_になります。

この小さくて巧妙なページ区切りの実装により、複数の結果ページをナビゲートできるようになります。

最先端の検索体験を構築する準備はできましたか?

十分に高度な検索は 1 人の努力だけでは実現できません。Elasticsearch は、データ サイエンティスト、ML オペレーター、エンジニアなど、あなたと同じように検索に情熱を傾ける多くの人々によって支えられています。ぜひつながり、協力して、希望する結果が得られる魔法の検索エクスペリエンスを構築しましょう。

はじめましょう