Skip to content

Filtro por _id na busca não funciona na API v2: recomendados, compre-junto, favoritos e kits ficam vazios #1306

Description

@vitorrgg

Resumo

Filtrar por _id na busca não funciona na API v2 (ecomplus.io/v2/search/_els). O mesmo filtro funciona na v1 (apx-search.e-com.plus/api/v1). Como todo componente que busca produtos por ID passa por EcomSearch.setProductIds(), e ele monta {terms: {_id: [...]}}, essas vitrines voltam vazias — e somem sem erro, porque o template tem v-if="items.length".

Nas lojas Cloud Commerce isso está ativo hoje: o vbeta-app do @cloudcommerce/storefront seta window.ECOMCLIENT_API_SEARCH = 'https://ecomplus.io/v2/search/_els/', então o app já fala com a v2.

Reprodução

Mesmo produto (5f3432a4f023684cdbd9c78d, loja 1024), mesma query, endpoints diferentes.

Por sku na v2 — 1 hit:

curl -s -X POST -H "X-Store-ID: 1024" -H "Content-Type: application/json" \
  -d '{"size":3,"query":{"bool":{"filter":[{"terms":{"sku":["PA606"]}}]}}}' \
  "https://ecomplus.io/v2/search/_els/items.json"

Por _id na v2 — total: 0:

curl -s -X POST -H "X-Store-ID: 1024" -H "Content-Type: application/json" \
  -d '{"size":3,"query":{"bool":{"filter":[{"terms":{"_id":["5f3432a4f023684cdbd9c78d"]}}]}}}' \
  "https://ecomplus.io/v2/search/_els/items.json"

O mesmo terms._id na v1 — funciona:

curl -s -X POST -H "X-Store-ID: 1024" -H "Content-Type: application/json" \
  -d '{"size":3,"query":{"bool":{"filter":[{"terms":{"_id":["5f3432a4f023684cdbd9c78d","5d09191d24607a6a42d71361"]}}]}}}' \
  "https://apx-search.e-com.plus/api/v1/items.json"

Rodando a query completa do RecommendedItems (com quantity > 0 e available: true) sobre os IDs que a Graphs API devolve para um produto real: 4 produtos na v1, 0 na v2.

Detalhe útil: a query ids funciona na v2. É só term/terms sobre _id que não.
Correção (editado): a query ids NÃO funciona na v2 — ela é descartada pelo proxy e a busca devolve o catálogo inteiro (meu teste original parecia passar porque os ids pedidos eram, por coincidência, os primeiros da ordenação default). O mapeamento completo do que funciona está no comentário abaixo.

Onde quebra

Tudo que passa por setProductIds, que delega para commonFilter e monta terms._id:

  • src/js/RecommendedItems.js:141 — vitrine de recomendados no carrinho (TheCart.html) e no checkout (EcCheckout.html)
  • src/js/RecommendedItems.js:149 — mesma vitrine com productIds explícito, que é como TheAccount.html:73 renderiza os favoritos
  • src/js/BuyTogether.js:157 — compre junto
  • src/js/TheProduct.js:493 — composição de kit

Nenhum deles loga erro: o fetch resolve com zero itens e o v-if esconde a seção.

Quem é afetado

  • Lojas Cloud Commerce (v3): afetadas, porque o vbeta-app aponta a busca para a v2.
  • Lojas do template v2 legado: não afetadas por isso — continuam na v1, onde o filtro funciona. Em compensação, o índice v1 está defasado. Comparando a mesma loja: v1 devolve "Achocolatado Em Pó 180g" e "Granola Low Carb 180g", v2 devolve "Achocolatado em Pó 180g" e "Granola Low Carb Tia Sônia 180g Baixo Carboidrato Rica em Fibras". São índices diferentes.

Ou seja: apontar o app legado para a v2 corrige a defasagem do catálogo e quebra a busca por ID. Hoje cada família de loja está de um lado desse trade-off.

O que não consegui determinar

Se o comportamento da v2 é bug ou decisão de projeto. O proxy search/_els é da plataforma e não está neste repositório, então não dá para olhar o mapeamento do índice a partir daqui. Essa é a pergunta que destrava o resto.

Caminhos possíveis

  1. Corrigir o proxy _els da v2. Resolve os quatro consumidores de uma vez, sem publicar nada nem bumpar versão em loja nenhuma. Depende de quem mantém o serviço — especificação e critérios de aceite na seção abaixo.
  2. Trocar terms._id por uma query ids no setProductIds. Inviável — a query ids é ignorada pela v2 (ver correção acima e comentário abaixo). O caminho client-side viável é outro: rotear buscas por _id pelo ?q=_id:(...) puro, que funciona nas duas APIs — implementado em fix(fetch): workaround Search API v2 to fix products search by IDs search-engine#324.
  3. Não fazer nada nos componentes legados e tratar caso a caso onde a vitrine importa.

A opção 2 (revisada) foi entregue, mas a 1 continua valendo por três motivos: (a) busca por _id com aggregations — página de coleção com UI de filtros — segue quebrada na v2 mesmo com a PR, que só roteia queries sem aggs; (b) o fail-open do proxy (cláusula desconhecida → catálogo inteiro) é um risco latente para qualquer consumidor, não só estes quatro; (c) com o proxy corrigido, o workaround client-side pode ser revertido no futuro.

Especificação para o conserto do proxy (caminho 1)

Consolidando aqui o mapeamento que estava só em comentário. Todos os testes contra a loja 1024; ids reais usados: 5d09193d24607a6a42d71399 (Tapioca, com estoque) e 5d09191d24607a6a42d71361 (Granola Low Carb, quantity: 184, available: true).

Comportamentos a corrigir, por prioridade:

P1 — term/terms sobre _id no body retorna 0 hits. É o que quebra o caminho principal do setProductIds. Critério de aceite:

curl -s -X POST -H "X-Store-ID: 1024" -H "Content-Type: application/json" \
  -d '{"size":3,"query":{"bool":{"filter":[{"terms":{"_id":["5d09193d24607a6a42d71399"]}}]}}}' \
  "https://ecomplus.io/v2/search/_els/items.json"

Esperado: 1 hit (o doc existe — trocando _id por sku no mesmo filtro, ele volta). Hoje: total: 0.

P2 — cláusulas não reconhecidas são descartadas silenciosamente (fail-open). ids, match, query_string, bool.must e term com {value:} são ignorados e a busca devolve o catálogo inteiro. Para um consumidor com v-if isso é vitrine vazia; para qualquer outro é resultado errado apresentado como certo. Critério de aceite: cláusula não suportada deve ou ser honrada ou retornar 400 — nunca ser removida da query.

curl -s -X POST -H "X-Store-ID: 1024" -H "Content-Type: application/json" \
  -d '{"size":3,"query":{"ids":{"values":["5d09193d24607a6a42d71399"]}}}' \
  "https://ecomplus.io/v2/search/_els/items.json"

Esperado: 1 hit ou 400. Hoje: total: 167 (catálogo inteiro, ordem default).

P3 — composição no q= (GET) é inconsistente. q=_id:("A" "B") sozinho funciona; composto, quebra de duas formas diferentes:

# derruba a Granola, que é available: true → esperado total 2, hoje total 1
curl -s -G -H "X-Store-ID: 1024" \
  --data-urlencode 'q=_id:("5d09193d24607a6a42d71399" "5d09191d24607a6a42d71361") AND available:true' \
  "https://ecomplus.io/v2/search/_els/items.json"

# a forma que a composição de kit emite hoje via fetch(true) → esperado total 2, hoje total 167
curl -s -G -H "X-Store-ID: 1024" \
  --data-urlencode 'q=visible:true AND _id:("5d09193d24607a6a42d71399" "5d09191d24607a6a42d71361")' \
  "https://ecomplus.io/v2/search/_els/items.json"

P4 — ranges e sort no GET não funcionam. q=_id:X AND quantity:>0 e quantity:[1 TO *] retornam 0 mesmo com o doc tendo quantity: 184; &sort=price:desc é ignorado (verificável com q=available:true&sort=price:desc&size=2, que volta preços fora de ordem). Menor prioridade — o workaround client-side já cobre — mas documenta a distância entre o _els e o contrato ES que os clientes assumem.

Nota

Isso não bloqueia ecomplus/cloud-commerce#812, que passa a renderizar recomendação no carrinho e checkout das lojas v3 por fora do cliente legado, buscando com api.get('search/v1?_id='), que funciona. Aquele PR não conserta os quatro componentes acima — só substitui a vitrine do carrinho e do checkout.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions