Skip to content

Usa Silver como fonte do OpenAlex match no ETL#727

Open
pitangainnovare wants to merge 23 commits into
scieloorg:mainfrom
pitangainnovare:feat/openalex-matcher-silver
Open

Usa Silver como fonte do OpenAlex match no ETL#727
pitangainnovare wants to merge 23 commits into
scieloorg:mainfrom
pitangainnovare:feat/openalex-matcher-silver

Conversation

@pitangainnovare

@pitangainnovare pitangainnovare commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

O que esse PR faz?

Altera o fluxo de OpenAlex matching do ETL para usar documentos já normalizados no índice Silver como fonte de candidatos, em vez de consultar e reprocessar documentos raw de OpenAlex. Observação: boa parte do diff é fixture de teste. São 585 linhas em JSON fixtures usadas para cobrir cenários reais de match/merge com Silver.

Principais mudanças:

  • adapta buscas por DOI, ISBN e título para campos do modelo Silver;
  • filtra candidatos que possuem identificador OpenAlex;
  • faz o matcher retornar SilverDocument;
  • remove a restandardização de candidatos OpenAlex raw no pipeline;
  • preserva content_url de candidatos Silver no merge;
  • adiciona fixtures e testes cobrindo article, book e book-chapter.

Onde a revisão poderia começar?

Começaria por:

etl/deduplicator/openalex.py

Depois seguiria para:

etl/pipeline.py
etl/transform/merger.py
etl/tests/pipeline/test_pipeline_dedup.py

Como este poderia ser testado manualmente?

  1. Garantir que os EtlPipelineConfig estejam apontando openalex_index para silver_scientific_production.
  2. Rodar um ETL pequeno para um documento SciELO com DOI/ISBN conhecido.
  3. Verificar no resultado indexado em Silver se:
    • houve match OpenAlex;
    • oca_data.merge_trace.openalex_matches foi preenchido;
    • ids.openalex foi preservado;
    • metadados OpenAlex esperados foram incorporados sem substituir indevidamente dados SciELO.

Validação

Para validar este PR, é suficiente rodar a suíte focada de ETL abaixo, que foi alterara para usar o silver_scientific_production no lugar do raw_openalex_works. Ela cobre as regras de deduplicação, o matching OpenAlex contra documentos Silver e a mescla SciELO/OpenAlex, incluindo preservação de IDs, trace e campos enriquecidos.

python manage.py test etl.tests.pipeline.test_pipeline_dedup etl.tests.transform.test_merger

Algum cenário de contexto que queira dar?

O índice Silver já contém documentos OpenAlex normalizados. Usar esse índice como fonte de match evita repetir a standardização de documentos raw durante o merge SciELO/OpenAlex e aproxima o matching do formato final consumido pelo restante da aplicação. E o mais importante é evitar que tenhamos um índice raw_openalex_works (que está disponível apenas no servidor legado).

Screenshots

N/A

Quais são tickets relevantes?

#719

Referências

N/A

Comment thread etl/deduplicator/openalex.py Outdated
Comment on lines +383 to +393
oca_data = (
candidate.get("oca_data")
if isinstance(candidate.get("oca_data"), dict)
else {}
)

oca_openalex = (
oca_data.get("openalex")
if isinstance(oca_data.get("openalex"), dict)
else {}
)

@samuelveigarangel samuelveigarangel Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oca_ids = (
candidate.get("oca_data", {})
.get("openalex", {})
.get("ids")
)
Se tiver a certeza que candidate["oca_data"] e candidate["oca_data"]["openalex"] são sempre dicionários, poderia simplificar removendo os isinstance

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% certeza é dificil garantir num universo de dados desse tamanho. Podemos adotar algo que projeta com a chave apontando para None. Algo parecido com a sua sugestão, mas que projete um passo além:

oca_data = candidate.get("oca_data") or {}
openalex = oca_data.get("openalex") or {}
oca_ids = openalex.get("ids")

Ou de forma mais enxuta:

oca_ids = ((candidate.get("oca_data") or {}).get("openalex") or {}).get("ids")

Comment thread etl/deduplicator/openalex.py Outdated
elif oca_ids:
values.append(oca_ids)

for value in values:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Em cada if...elif, faz um for em oa_ids e oca_ids e faz o return dentro dele. Não precisa de uma lista para adicionar os itens e depois interar nesse for.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Esse _first_openalex_id está legado (tinha a ver com o raw) - o sistema deve olhar para todos os IDs OpenaAlex de um doc (e como estamos olhando para o silver, agora pode haver mais de um válido). Vou fazer uma correção.

- o correto, a partir do silver, é obter todos os IDs OpenAlex
- e não apenas o primeiro ID, como era o método substituído
- a versão anterior considerava apenas o primeiro encontrado
- cria utilitário interno para facilitar comparação
- cria três testes para avaliar ordem de mescla com all ids
- o alias silver_scientific_production contem docs mesclados
- isso complica a mescla e deve ser tratado em outro PR
- este PR envolve substituir raw_openalex_works por silver_openalex-*
- esses procedimentos permitiam realizar mescla fora da rotina padrão
- e potencialmente estragam a mescla, se executadas de maneira indevida
- perderam o sentido, com a troca para silver
- havia função em task servindo de apoio para managed command
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants