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=[''], post_tags=[''] ) # 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 }