feat: adicionar sistema de sugestao de consultores por tema
- Novo endpoint GET /api/v1/consultores/sugerir com busca por tema - Busca inteligente em areas de avaliacao, conhecimento e pesquisa - Filtro por consultores ativos e area de avaliacao especifica - Endpoint GET /api/v1/consultores/areas-avaliacao com lista de areas - Novo componente SugerirConsultores no frontend - Botao 'Sugerir por Tema' integrado na interface principal - Score de match baseado em relevancia do tema e experiencia
This commit is contained in:
@@ -525,3 +525,189 @@ class ElasticsearchClient:
|
||||
finally:
|
||||
if scroll_id:
|
||||
await self.limpar_scroll(scroll_id)
|
||||
|
||||
async def sugerir_consultores(
|
||||
self,
|
||||
tema: str,
|
||||
area_avaliacao: Optional[str] = None,
|
||||
apenas_ativos: bool = True,
|
||||
size: int = 20
|
||||
) -> list:
|
||||
must_conditions = []
|
||||
should_conditions = []
|
||||
|
||||
tema_lower = tema.lower().strip()
|
||||
|
||||
should_conditions.extend([
|
||||
{
|
||||
"nested": {
|
||||
"path": "atuacoes",
|
||||
"query": {
|
||||
"bool": {
|
||||
"must": [
|
||||
{"term": {"atuacoes.tipo": "Consultor"}},
|
||||
{
|
||||
"bool": {
|
||||
"should": [
|
||||
{"match": {"atuacoes.dadosConsultoria.areaConhecimentoPos.nome": {"query": tema, "boost": 3}}},
|
||||
{"match": {"atuacoes.dadosConsultoria.areaConhecimentoPos.areaAvaliacao.nome": {"query": tema, "boost": 5}}},
|
||||
{"match": {"atuacoes.dadosConsultoria.areaPesquisa.descricao": {"query": tema, "boost": 2}}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"score_mode": "max",
|
||||
"boost": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"nested": {
|
||||
"path": "atuacoes",
|
||||
"query": {
|
||||
"bool": {
|
||||
"should": [
|
||||
{"term": {"atuacoes.tipo": {"value": "Coordenação de Área de Avaliação", "boost": 8}}},
|
||||
{"term": {"atuacoes.tipo": {"value": "Histórico de Coordenação de Área de Avaliação", "boost": 4}}}
|
||||
]
|
||||
}
|
||||
},
|
||||
"score_mode": "sum"
|
||||
}
|
||||
},
|
||||
{
|
||||
"nested": {
|
||||
"path": "atuacoes",
|
||||
"query": {
|
||||
"bool": {
|
||||
"should": [
|
||||
{"term": {"atuacoes.tipo": {"value": "Premiação Prêmio", "boost": 3}}},
|
||||
{"term": {"atuacoes.tipo": {"value": "Avaliação Prêmio", "boost": 2}}}
|
||||
]
|
||||
}
|
||||
},
|
||||
"score_mode": "sum"
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
if area_avaliacao:
|
||||
must_conditions.append({
|
||||
"nested": {
|
||||
"path": "atuacoes",
|
||||
"query": {
|
||||
"bool": {
|
||||
"must": [
|
||||
{"term": {"atuacoes.tipo": "Consultor"}},
|
||||
{"match": {"atuacoes.dadosConsultoria.areaConhecimentoPos.areaAvaliacao.nome": area_avaliacao}}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if apenas_ativos:
|
||||
must_conditions.append({
|
||||
"nested": {
|
||||
"path": "atuacoes",
|
||||
"query": {
|
||||
"bool": {
|
||||
"must": [
|
||||
{"term": {"atuacoes.tipo": "Consultor"}}
|
||||
],
|
||||
"should": [
|
||||
{"match": {"atuacoes.dadosConsultoria.situacaoConsultoria": "Atividade Contínua"}},
|
||||
{"match": {"atuacoes.dadosConsultoria.situacaoConsultoria": "Ativo"}},
|
||||
{"match": {"atuacoes.dadosConsultoria.situacaoConsultoria": "Contínua"}}
|
||||
],
|
||||
"minimum_should_match": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
query = {
|
||||
"size": size,
|
||||
"query": {
|
||||
"bool": {
|
||||
"must": must_conditions if must_conditions else [{"match_all": {}}],
|
||||
"should": should_conditions,
|
||||
"minimum_should_match": 1
|
||||
}
|
||||
},
|
||||
"_source": ["id", "dadosPessoais", "atuacoes"],
|
||||
"sort": [{"_score": "desc"}]
|
||||
}
|
||||
|
||||
try:
|
||||
response = await self.client.post(
|
||||
f"{self.url}/{self.index}/_search",
|
||||
json=query,
|
||||
timeout=60.0
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
results = []
|
||||
for hit in data.get("hits", {}).get("hits", []):
|
||||
doc = hit["_source"]
|
||||
doc["_score_match"] = hit.get("_score", 0)
|
||||
results.append(doc)
|
||||
return results
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Erro ao sugerir consultores: {e}")
|
||||
|
||||
async def listar_areas_avaliacao(self) -> list:
|
||||
areas_conhecidas = [
|
||||
"ADMINISTRAÇÃO PÚBLICA E DE EMPRESAS, CIÊNCIAS CONTÁBEIS E TURISMO",
|
||||
"ANTROPOLOGIA E ARQUEOLOGIA",
|
||||
"ARQUITETURA, URBANISMO E DESIGN",
|
||||
"ARTES",
|
||||
"ASTRONOMIA E FÍSICA",
|
||||
"BIODIVERSIDADE",
|
||||
"BIOTECNOLOGIA",
|
||||
"CIÊNCIA DA COMPUTAÇÃO",
|
||||
"CIÊNCIA DE ALIMENTOS",
|
||||
"CIÊNCIA POLÍTICA E RELAÇÕES INTERNACIONAIS",
|
||||
"CIÊNCIAS AGRÁRIAS I",
|
||||
"CIÊNCIAS AMBIENTAIS",
|
||||
"CIÊNCIAS BIOLÓGICAS I",
|
||||
"CIÊNCIAS BIOLÓGICAS II",
|
||||
"CIÊNCIAS BIOLÓGICAS III",
|
||||
"CIÊNCIAS DA RELIGIÃO E TEOLOGIA",
|
||||
"COMUNICAÇÃO E INFORMAÇÃO E MUSEOLOGIA",
|
||||
"DIREITO",
|
||||
"ECONOMIA",
|
||||
"EDUCAÇÃO",
|
||||
"EDUCAÇÃO FÍSICA",
|
||||
"ENFERMAGEM",
|
||||
"ENGENHARIAS I",
|
||||
"ENGENHARIAS II",
|
||||
"ENGENHARIAS III",
|
||||
"ENGENHARIAS IV",
|
||||
"ENSINO",
|
||||
"FARMÁCIA",
|
||||
"FILOSOFIA",
|
||||
"GEOGRAFIA",
|
||||
"GEOCIÊNCIAS",
|
||||
"HISTÓRIA",
|
||||
"INTERDISCIPLINAR",
|
||||
"LETRAS E LINGUÍSTICA",
|
||||
"MATEMÁTICA E ESTATÍSTICA",
|
||||
"MATERIAIS",
|
||||
"MEDICINA I",
|
||||
"MEDICINA II",
|
||||
"MEDICINA III",
|
||||
"MEDICINA VETERINÁRIA",
|
||||
"NUTRIÇÃO",
|
||||
"ODONTOLOGIA",
|
||||
"PLANEJAMENTO URBANO E REGIONAL E DEMOGRAFIA",
|
||||
"PSICOLOGIA",
|
||||
"QUÍMICA",
|
||||
"SAÚDE COLETIVA",
|
||||
"SERVIÇO SOCIAL",
|
||||
"SOCIOLOGIA",
|
||||
"ZOOTECNIA E RECURSOS PESQUEIROS"
|
||||
]
|
||||
return [{"nome": area, "count": 0} for area in areas_conhecidas]
|
||||
|
||||
Reference in New Issue
Block a user