Paginação
Muitas vezes, é impraticável para uma aplicação lidar com um número muito grande de resultados. Por esse motivo, APIs e serviços web utilizam controles de paginação para permitir que os aplicativos solicitem os resultados em pequenos blocos ou páginas.
Você deve ter notado que, por padrão, o Elasticsearch não retorna mais de 10 resultados. O parâmetro opcional size pode ser fornecido em uma solicitação de pesquisa para alterar esse valor máximo. O exemplo a seguir solicita que sejam retornados até 5 resultados de pesquisa:
results = es.search(
query={
'multi_match': {
'query': query,
'fields': ['name', 'summary', 'content'],
}
}, size=5
)Para acessar páginas adicionais de resultados, o parâmetro from_ é usado, que indica de onde na lista completa de resultados começar (já que from é uma palavra-chave reservada em Python, from_ é usado).
O próximo exemplo recupera uma segunda página com 5 resultados:
results = es.search(
query={
'multi_match': {
'query': query,
'fields': ['name', 'summary', 'content'],
}
}, size=5, from_=5
)Vamos incorporar size e from_ no endpoint handle_search() em app.py:
@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'])Aqui, o tamanho da página está agora fixo em 5 (sinta-se à vontade para usar qualquer outro número que desejar). O argumento from_ é considerado como um campo adicional no formulário enviado, mas este campo é considerado opcional, assumindo o valor padrão 0 quando não estiver presente.
O formulário de pesquisa disponível em index.html não possui um campo from_ , portanto, as pesquisas regulares sempre começarão a partir do primeiro resultado. O modelo exibe informações sobre o intervalo de resultados mostrados e qual é o total. Eis como isso é feito usando expressões de modelo:
<div class="col-sm-auto my-auto">
Showing results {{ from_ + 1 }}-{{ from_ + results|length }} out of {{ total }}.
</div>O modelo também inclui lógica para exibir botões de paginação para avançar ou retroceder na lista de resultados. Aqui está a implementação do botão "Resultados anteriores":
{% 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 %}Como você pode ver, o botão "Página anterior" só é exibido na página quando from_ é maior que zero. A implementação deste botão utiliza a API de histórico do navegador para voltar uma página.
O botão "Próxima página" tem uma implementação muito mais interessante:
{% 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 %}Na verdade, este botão não é um botão independente, mas sim um formulário completo que possui dois campos ocultos além do botão. O formulário é semelhante ao formulário de pesquisa principal, mas inclui o campo opcional from_ , ajustado para apontar para a próxima página de resultados. Ao clicar neste botão, o aplicativo Flask receberá uma solicitação de pesquisa deste formulário alternativo, que usa a mesma consulta de texto, mas um valor diferente de zero from_ .
Com essa implementação de paginação simples e inteligente, você poderá navegar por várias páginas de resultados.