68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
from elasticsearch_dsl import Q, Search
|
|
from .documents import DiarioOficialDocument
|
|
|
|
class DiarioOficialSearchService:
|
|
@staticmethod
|
|
def search(query, highlight=True, fuzziness=1, page=1, page_size=10, tipos=None, data_inicio=None, data_fim=None):
|
|
# Configura a busca básica
|
|
s = DiarioOficialDocument.search().source(excludes=['page_content.content'])
|
|
|
|
# Filtros
|
|
if tipos:
|
|
s = s.filter('terms', tipo_nome=tipos)
|
|
if data_inicio and data_fim:
|
|
s = s.filter('range', data={'gte': data_inicio, 'lte': data_fim})
|
|
|
|
# Query principal com fuzziness e sinônimos
|
|
main_query = Q(
|
|
'multi_match',
|
|
query=query,
|
|
fields=[
|
|
'numero^3', # Maior peso para o número
|
|
'tipo_nome^2', # Peso médio para o tipo
|
|
'page_content.content' # Peso padrão para o conteúdo
|
|
],
|
|
fuzziness=fuzziness,
|
|
analyzer='portuguese_synonyms'
|
|
)
|
|
s = s.query(main_query)
|
|
|
|
# Highlighting
|
|
if highlight:
|
|
s = s.highlight(
|
|
'page_content.content',
|
|
fragment_size=150,
|
|
number_of_fragments=3,
|
|
pre_tags=['<mark>'],
|
|
post_tags=['</mark>']
|
|
)
|
|
|
|
# Paginação
|
|
start = (page - 1) * page_size
|
|
end = start + page_size
|
|
s = s[start:end]
|
|
|
|
# Executa a busca
|
|
response = s.execute()
|
|
|
|
# Formata os resultados
|
|
results = []
|
|
for hit in response:
|
|
result = {
|
|
'id': hit.id,
|
|
'numero': hit.numero,
|
|
'data': hit.data,
|
|
'link': hit.link,
|
|
'tipo_nome': hit.tipo_nome,
|
|
'score': hit.meta.score
|
|
}
|
|
if highlight and hasattr(hit.meta, 'highlight'):
|
|
result['highlights'] = hit.meta.highlight['page_content.content'].to_dict()
|
|
results.append(result)
|
|
|
|
return {
|
|
'total': response.hits.total.value,
|
|
'results': results
|
|
}
|
|
|