remove o modelo pdfdocument
This commit is contained in:
232
diarios/views.py
232
diarios/views.py
@ -1,80 +1,206 @@
|
||||
from django.shortcuts import render
|
||||
from elasticsearch_dsl import Q
|
||||
from datetime import datetime
|
||||
from .documents import DiarioOficialDocument
|
||||
from elasticsearch.exceptions import RequestError
|
||||
|
||||
def search_diarios(request):
|
||||
q = request.GET.get('q', '')
|
||||
page = int(request.GET.get('page', 1))
|
||||
size = int(request.GET.get('size', 10))
|
||||
|
||||
# Parâmetros de filtro de data
|
||||
date_start = request.GET.get('date_start', '')
|
||||
date_end = request.GET.get('date_end', '')
|
||||
|
||||
# Tipo de correspondência (exata ou parcial)
|
||||
match_type = request.GET.get('match_type', 'partial') # 'exact' ou 'partial'
|
||||
|
||||
start = (page - 1) * size
|
||||
end = start + size
|
||||
|
||||
|
||||
results = []
|
||||
total = 0
|
||||
did_you_mean = None
|
||||
search_suggestions = []
|
||||
|
||||
if q:
|
||||
# Busca principal com boost para relevância
|
||||
query = Q(
|
||||
'multi_match',
|
||||
query=q,
|
||||
fields=['content^3', 'tipo.nome^2', 'numero', 'pages.content'],
|
||||
fuzziness='AUTO'
|
||||
)
|
||||
|
||||
# Pesquisa com highlighting
|
||||
search = DiarioOficialDocument.search()
|
||||
search = search.query(query)
|
||||
search = search.highlight('content', fragment_size=150, number_of_fragments=3)
|
||||
search = search.highlight('pages.content', fragment_size=150, number_of_fragments=3)
|
||||
|
||||
# Paginação
|
||||
search = search[start:end]
|
||||
|
||||
response = search.execute()
|
||||
|
||||
total = response.hits.total.value
|
||||
|
||||
for hit in response:
|
||||
# Adicionar destaque
|
||||
highlight = ""
|
||||
if hasattr(hit.meta, 'highlight'):
|
||||
if 'content' in hit.meta.highlight:
|
||||
highlight = "...".join(hit.meta.highlight.content)
|
||||
try:
|
||||
if q:
|
||||
# Construir a consulta base
|
||||
search = DiarioOficialDocument.search()
|
||||
|
||||
# Determinar o tipo de consulta com base no match_type
|
||||
if match_type == 'exact':
|
||||
# Correspondência exata (frase exata)
|
||||
query = Q(
|
||||
'multi_match',
|
||||
query=q,
|
||||
fields=['content^3', 'tipo.nome^2', 'numero', 'pages.content'],
|
||||
type='phrase'
|
||||
)
|
||||
else:
|
||||
# Correspondência parcial (qualquer termo)
|
||||
query = Q(
|
||||
'multi_match',
|
||||
query=q,
|
||||
fields=['content^3', 'tipo.nome^2', 'numero', 'pages.content'],
|
||||
fuzziness='AUTO',
|
||||
operator='or' # Pelo menos um termo deve corresponder
|
||||
)
|
||||
|
||||
# Aplicar a consulta principal
|
||||
search = search.query(query)
|
||||
|
||||
# Aplicar filtros de data se fornecidos
|
||||
date_filters = []
|
||||
if date_start:
|
||||
try:
|
||||
date_start_obj = datetime.strptime(date_start, '%Y-%m-%d')
|
||||
date_filters.append(Q('range', data={'gte': date_start_obj}))
|
||||
except ValueError:
|
||||
pass # Ignorar datas inválidas
|
||||
|
||||
if date_end:
|
||||
try:
|
||||
date_end_obj = datetime.strptime(date_end, '%Y-%m-%d')
|
||||
date_filters.append(Q('range', data={'lte': date_end_obj}))
|
||||
except ValueError:
|
||||
pass # Ignorar datas inválidas
|
||||
|
||||
if date_filters:
|
||||
for date_filter in date_filters:
|
||||
search = search.filter(date_filter)
|
||||
|
||||
# Configuração do highlighting
|
||||
search = search.highlight('content', fragment_size=150, number_of_fragments=3)
|
||||
search = search.highlight('pages.content', fragment_size=150, number_of_fragments=3)
|
||||
|
||||
# Paginação
|
||||
total_search = search.count()
|
||||
search = search[start:end]
|
||||
|
||||
# Executar a pesquisa
|
||||
response = search.execute()
|
||||
|
||||
total = response.hits.total.value
|
||||
|
||||
# "Você quis dizer" - sugestão para termos com erros de digitação
|
||||
if total < 3 and q: # Se poucos resultados, sugira correções
|
||||
suggestion_search = DiarioOficialDocument.search()
|
||||
suggestion_search = suggestion_search.suggest(
|
||||
'phrase_suggestion',
|
||||
q,
|
||||
phrase={
|
||||
'field': 'content',
|
||||
'size': 5,
|
||||
'highlight': {
|
||||
'pre_tag': '<em>',
|
||||
'post_tag': '</em>'
|
||||
}
|
||||
}
|
||||
)
|
||||
suggestion_result = suggestion_search.execute()
|
||||
|
||||
# Processando páginas com destaque
|
||||
highlighted_pages = []
|
||||
if hasattr(hit.meta, 'highlight') and 'pages.content' in hit.meta.highlight:
|
||||
for i, content in enumerate(hit.meta.highlight['pages.content']):
|
||||
# Encontre a página correspondente
|
||||
page_number = i + 1 # Lógica simplificada, pode precisar de ajuste
|
||||
highlighted_pages.append({
|
||||
'number': page_number,
|
||||
'content': content
|
||||
})
|
||||
# Processe as sugestões
|
||||
if hasattr(suggestion_result, 'suggest') and 'phrase_suggestion' in suggestion_result.suggest:
|
||||
suggestions = suggestion_result.suggest['phrase_suggestion'][0]['options']
|
||||
if suggestions:
|
||||
for suggestion in suggestions:
|
||||
if suggestion['text'].lower() != q.lower():
|
||||
did_you_mean = suggestion['text']
|
||||
break
|
||||
# Gerar sugestões de pesquisa relacionadas
|
||||
if q:
|
||||
# Use a expansão de termos para sugerir pesquisas relacionadas
|
||||
related_search = DiarioOficialDocument.search()
|
||||
related_search = related_search.query(
|
||||
'more_like_this',
|
||||
fields=['content'],
|
||||
like=q,
|
||||
min_term_freq=1,
|
||||
max_query_terms=12
|
||||
)
|
||||
related_search = related_search[:5] # Limite para 5 sugestões
|
||||
|
||||
try:
|
||||
related_results = related_search.execute()
|
||||
|
||||
# Extraia termos relevantes dos resultados relacionados
|
||||
for hit in related_results:
|
||||
if hasattr(hit, 'content') and hit.content:
|
||||
# Extraia alguns termos significativos do conteúdo
|
||||
content_terms = hit.content.split()[:10] # Primeiros 10 termos
|
||||
suggestion = ' '.join(content_terms)
|
||||
if suggestion not in search_suggestions and suggestion != q:
|
||||
search_suggestions.append(suggestion)
|
||||
if len(search_suggestions) >= 5: # Limite para 5 sugestões
|
||||
break
|
||||
except:
|
||||
# Ignore erros de sugestões relacionadas
|
||||
pass
|
||||
|
||||
# Combine dados do documento com os destaques
|
||||
result = {
|
||||
'id': hit.id,
|
||||
'tipo': hit.tipo.nome if hasattr(hit, 'tipo') and hit.tipo else '',
|
||||
'numero': hit.numero,
|
||||
'data': hit.data,
|
||||
'link': hit.link,
|
||||
'highlight': highlight,
|
||||
'highlighted_pages': highlighted_pages
|
||||
}
|
||||
|
||||
results.append(result)
|
||||
|
||||
# Processar resultados
|
||||
for hit in response:
|
||||
# Adicionar destaque
|
||||
highlight = ""
|
||||
if hasattr(hit.meta, 'highlight'):
|
||||
if 'content' in hit.meta.highlight:
|
||||
highlight = "...".join(hit.meta.highlight.content)
|
||||
|
||||
# Processar páginas com destaque
|
||||
highlighted_pages = []
|
||||
total_occurrences = 0
|
||||
|
||||
if hasattr(hit.meta, 'highlight') and 'pages.content' in hit.meta.highlight:
|
||||
# Calcular o número total de ocorrências
|
||||
for content in hit.meta.highlight['pages.content']:
|
||||
# Contar o número de <em> tags, que representam termos destacados
|
||||
total_occurrences += content.count('<em>')
|
||||
|
||||
# Processar os destaques por página
|
||||
for i, content in enumerate(hit.meta.highlight['pages.content']):
|
||||
# Encontre a página correspondente
|
||||
page_number = i + 1 # Lógica simplificada, pode precisar de ajuste
|
||||
highlighted_pages.append({
|
||||
'number': page_number,
|
||||
'content': content
|
||||
})
|
||||
|
||||
# Combine dados do documento com os destaques
|
||||
result = {
|
||||
'id': hit.id,
|
||||
'tipo': hit.tipo.nome if hasattr(hit, 'tipo') and hit.tipo else '',
|
||||
'numero': hit.numero,
|
||||
'data': hit.data,
|
||||
'link': hit.link,
|
||||
'highlight': highlight,
|
||||
'highlighted_pages': highlighted_pages,
|
||||
'occurrences': total_occurrences
|
||||
}
|
||||
|
||||
results.append(result)
|
||||
except RequestError as e:
|
||||
# Tratar erros de consulta do Elasticsearch
|
||||
error_message = str(e)
|
||||
return render(request, 'diarios/diarios_search.html', {
|
||||
'error': error_message,
|
||||
'query': q
|
||||
})
|
||||
|
||||
context = {
|
||||
'query': q,
|
||||
'date_start': date_start,
|
||||
'date_end': date_end,
|
||||
'match_type': match_type,
|
||||
'results': results,
|
||||
'total': total,
|
||||
'page': page,
|
||||
'size': size,
|
||||
'total_pages': (total + size - 1) // size if total > 0 else 0,
|
||||
'did_you_mean': did_you_mean,
|
||||
'search_suggestions': search_suggestions[:5] # Limite para 5 sugestões
|
||||
}
|
||||
|
||||
|
||||
return render(request, 'diarios/diarios_search.html', context)
|
||||
|
||||
def diario_detail(request, pk):
|
||||
|
||||
Reference in New Issue
Block a user