Skip to content

Adiciona coleta e indexação de artigos SciELO via ArticleMeta#733

Open
samuelveigarangel wants to merge 9 commits into
scieloorg:mainfrom
samuelveigarangel:issue-631
Open

Adiciona coleta e indexação de artigos SciELO via ArticleMeta#733
samuelveigarangel wants to merge 9 commits into
scieloorg:mainfrom
samuelveigarangel:issue-631

Conversation

@samuelveigarangel

@samuelveigarangel samuelveigarangel commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

O que esse PR faz?

Adiciona suporte completo à coleta de artigos SciELO no módulo harvest, integrando a API ArticleMeta ao pipeline já existente (preprints, books, SciELO Data).

Principais entregas:

  • Modelos e persistência: HarvestedArticle, HarvestErrorLogArticle e migration 0004
  • Coleta: serviço em harvest_articles.py com paginação incremental, busca de identificadores e detalhes por artigo, tratamento de falhas e registro de datestamp
  • Tasks Celery: harvest_scielo_articles (coleta), retry_failed_articles (reprocessamento) e reindex_failed_articles (reindexação)
  • Indexação raw: signals de pre_save/post_save, suporte em indexing.py e configuração OS_INDEX_RAW_ARTICLE
  • OpenSearch: mapping bronze (mapping_bronze_articles.py) e extensão dos commands create_raw_indices e create_bronze_indices para o tipo article
  • Admin Wagtail: snippet HarvestedArticle no grupo Harvest
  • Testes: cobertura de coleta, persistência, incremental por datestamp e get_index_name
  • O fluxo segue o padrão dos demais tipos de documento: coleta → persistência no Postgres → indexação automática no índice raw via signal.

Onde a revisão poderia começar?

Sugestão de ordem:

  1. harvest/harvests/harvest_articles.py — lógica central da coleta (API ArticleMeta, paginação, persistência e tratamento de erros)
  2. harvest/tasks.py — integração Celery (harvest_scielo_articles, retry_failed_articles, reindex_failed_articles, reconciliação)
  3. harvest/signals.py e harvest/indexing.py — indexação automática no OpenSearch
  4. harvest/mapping_bronze_articles.py e commands em harvest/management/commands/ — estrutura dos índices raw/bronze
  5. harvest/tests.py — cenários cobertos e comportamento esperado

Como este poderia ser testado manualmente?

Pré-requisitos

make django_migrate

Variáveis de ambiente (ex.: .envs/.local/.django):

  1. Criar índices OpenSearch
docker compose -f local.yml run --rm django python manage.py create_raw_indices --index article
docker compose -f local.yml run --rm django python manage.py create_bronze_indices --index article
  1. Executar coleta (lote pequeno para teste)

Via shell Django/Celery:

from django.contrib.auth import get_user_model
from harvest.tasks import harvest_scielo_articles

user = get_user_model().objects.first()
harvest_scielo_articles(
    username=user.username,
    limit=5,
    offset=0,
    from_date="2021-01-01",
    until_date="2021-12-31",
    collection="scl",
)
  1. Validar persistência

Admin Wagtail → Harvest → Articles
Conferir harvest_status, index_status, identifier, datestamp e raw_data
4. Validar indexação raw

Verificar documentos no índice raw_scielo_article no OpenSearch
Confirmar que artigos com harvest_status=success têm index_status=success
5. Testar retry e reindex

from harvest.tasks import retry_failed_articles, reindex_failed_articles

retry_failed_articles(username=user.username)
reindex_failed_articles()
  1. Rodar testes automatizados
make django_test
# ou focado:
docker compose -f local.yml run --rm django python manage.py test harvest.tests.HarvestArtic

Algum cenário de contexto que queira dar?

Indique um contexto onde as modificações se fazem necessárias ou passe informações que contextualizam
o revisor a fim de facilitar o entendimento da funcionalidade.

Screenshots

Quando aplicável e se fizer possível adicione screenshots que remetem a situação gráfica do problema que o pull request resolve.

Quais são tickets relevantes?

CLOSED #631

Referências

Indique as referências utilizadas para a elaboração do pull request.

samuelveigarangel and others added 9 commits July 6, 2026 10:34
Expõe harvest_scielo_articles com suporte a paginação, filtros de data e coleção.

Co-authored-by: Cursor <cursoragent@cursor.com>
Inclui reprocessamento de coletas com falha, reindexação e suporte a article na reconciliação.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cria as tabelas necessárias para persistir artigos coletados via ArticleMeta.

Co-authored-by: Cursor <cursoragent@cursor.com>
Define ARTICLEMETA_BASE_URL e OS_INDEX_RAW_ARTICLE para a coleta SciELO.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adiciona suporte a HarvestedArticle em get_index_name e signals de save/pre_save.

Co-authored-by: Cursor <cursoragent@cursor.com>
Inclui comandos de criação de índices raw/bronze e melhora log de erro na transformação.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cobre paginação ArticleMeta, persistência, retry incremental e get_index_name.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expõe artigos coletados no grupo Harvest com listagem e filtros de status.

Co-authored-by: Cursor <cursoragent@cursor.com>
@samuelveigarangel samuelveigarangel changed the title Issue 631 [WIP] Issue 631 Jul 6, 2026
@samuelveigarangel samuelveigarangel changed the title [WIP] Issue 631 [WIP] Adiciona coleta e indexação de artigos SciELO via ArticleMeta Jul 6, 2026

@pitangainnovare pitangainnovare left a comment

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.

Há alguns ajustes finos que podem melhorar a legibilidade. Senti falta da fixture de TransformationScript para já testar a transformação dos dados até o Bronze (ou isso está fora do escopo deste PR?).

Comment thread harvest/tasks.py
return

for identifier in failed_identifiers:
article = HarvestedArticle.objects.filter(identifier=identifier).first()

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.

Não seria melhor usar o .get no lugar do .filter.first? Ou isso é uma defesa para o caso de existir mais de um article com o mesmo identifier?

Comment thread harvest/tasks.py


@celery_app.task(name="Retry failed articles")
def retry_failed_articles(username, user_id=None):

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.

pelo que entendi, ha duas etapas

  1. harvest
  2. index

o nome dessa task nao deveria ser algo como harvest_failed_articles? Assim fica mais facil de entender e diferencia bem da outra que é chamada de reindex_failed_articles.

"verbose_name_plural": "Dados de artigos SciELO",
},
),
migrations.CreateModel(

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.

Não seria melhor indexar os erros no índice harverst_errors (opensearch) em lugar de termos um modelo pra isso?

params["collection"] = collection
url = _build_url("/api/v1/article/", params)
payload = fetch_data(url, headers=headers, json=True, timeout=60, verify=True)
payload.pop("citations", None)

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.

:)

Comment on lines +232 to +241
value = (
raw_data.get("processing_date")
or article_data.get("processing_date")
or raw_data.get("updated_at")
or article_data.get("updated_at")
or raw_data.get("created_at")
or article_data.get("created_at")
)
if not value:
return None

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.

Diria que apenas o campo processing_date é necessário. Se raw_data for a resposta do articlemeta, então esse campo sempre vai existir.

},
},
},
"type": {"type": "keyword"},

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.

Precisa confirmar se tbm está assim nos outros casos (book, dataset, preprint), quero dizer, sem subtipo type.keyword.

"analyzer": "multilingual",
"fields": {"keyword": {"type": "keyword", "ignore_above": 256}},
},
"title_with_lang": {

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.

Não faltou o copy_to? Ou aqui não é necessário pois fazemos isso no silver?

Comment thread harvest/models.py
)


class HarvestErrorLogArticle(BaseHarvestErrorLog):

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.

Pode ser mais interessante logar no índice harvest_errors no OpenSearch. É só uma ideia que já conversamos, mas nada que impeça a aprovação. No caso do articles, isso pode ser mais chato de ver os erros via DB Postgres, pois são milhares de registros (pode ser ruim ver via tela Wagtail).

Comment thread harvest/tasks.py
Comment on lines +240 to +241
exc_context.save_to_db()
exc_context.mark_status_harvest()

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.

Está meio estranho de ler, pois primeiro salva e depois marca o status. Olhando o código do ExceptionContext, entendi o porquê.

@samuelveigarangel samuelveigarangel changed the title [WIP] Adiciona coleta e indexação de artigos SciELO via ArticleMeta Adiciona coleta e indexação de artigos SciELO via ArticleMeta Jul 17, 2026
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.

Criar mecanismo para sincronizar dados de SciELO Articles com índice bronze

2 participants