Repository navigation
Filtro por _id na busca não funciona na API v2: recomendados, compre-junto, favoritos e kits ficam vazios #1306
Description
Activity
Reverifiquei o comportamento da v2 com mais cuidado e o quadro mudou — corrigi o corpo da issue e abri PR com a solução client-side.
Mapeamento completo do
?q=/DSL na v2 (/v2/search/_els)forma resultado body terms/termsobre_id0 hits (aplicado, não casa) body ids,match,query_string,bool.must,termcom{value:}descartados → devolve o catálogo inteiro GET q=_id:("A" "B")sozinho✅ funciona, hits exatos GET q=_id:(...) AND available:true❌ derruba doc que é available: trueGET q=visible:true AND _id:(...)(forma que o kit emite hoje viafetch(true))❌ catálogo inteiro ( total: 167)GET q=... quantity:>0ou[1 TO *]❌ 0 hits mesmo com quantity: 184no docGET &sort=price:desc❌ ignorado Ou seja: na v2 a única forma confiável de buscar por id é
q=_id:(...)puro — qualquer condição composta é traição. A afirmação anterior de que "a queryidsfunciona" estava errada (o teste passou por coincidência de ordenação) — e ela seria pior que o bug: renderizaria o catálogo inteiro como "recomendados".PR
ecomplus/search-engine#324 — o
fetch()passa a rotear busca com filtro por_idpara oq=puro, reaplicando os demais filtros, a ordenação (pela ordem dos ids pedidos) e a paginação no cliente. Testado contra as duas APIs com o build real: vitrine, paginação, kit (fetch(true)) e um controle sem_id— na v2 a vitrine sai de 0 hits para os produtos certos em ordem, e o kit sai de "catálogo inteiro" para os ids exatos; na v1 comportamento preservado.Cobre os quatro consumidores (recomendados, compre junto, favoritos, kit) porque todos passam por
setProductIdssem aggregations. Fora do escopo: busca por_idcom aggregations (página de coleção com UI de filtros) — na v1 segue funcionando, na v2 segue como está.O caminho 1 (corrigir o
_idno próprio proxy_els) continua sendo o ideal a longo prazo — a PR é o contorno que não depende de mudança na plataforma. Depois do release ainda falta o bump emstorefront-components/storefront-apppara as lojas herdarem.Corrigido no proxy (P1 e P3) em ecomplus-core/store-api#1314, publicado no
v2.0.0-rc.154, já em produção.Causa
- P1:
term/termssobre_idno body viravam$incom strings, mas o_idé armazenado como ObjectId, então nunca casavam. - P3: o
q=era lido com um únicosplit(':')sobre a string inteira. Comvisible:true AND _id:(...), o primeiro campo (visible) não era reconhecido e nada era filtrado. Com_id:(...) AND available:true, os ids eram cortados errado e o segundo virava inválido.
Validação em produção (
ecomplus.io/v2/search/_els, loja 1024)cenário antes agora P1: terms._id [5d09193d…]0 1 hit P1: reprodução original terms._id [5f3432a4…]0 1 hit (o mesmo doc que a busca por sku PA606)P3: q=_id:(A B) AND available:true1 2 hits P3: q=visible:true AND _id:(A B)(kit viafetch(true))167, o catálogo 2 hits Controles: q=sku:"PA606" OR name:"PA606"e busca sem filtro— sem mudança, com aggregationsOs quatro consumidores (recomendados, compre junto, favoritos e kit) voltam a funcionar nas lojas Cloud Commerce sem publicar nada no search-engine ou no storefront. ecomplus/search-engine#324 fica fechado.
Continuam em aberto
- P2: cláusulas não suportadas (
ids,match,query_string…) ainda são descartadas e a busca devolve o catálogo inteiro. - P4:
rangeesortdentro doq=no GET ainda não são suportados.
🤖 Generated with Claude Code
- P1:
- added a commit that references this issue
on Sep 28, 2026
Resumo
Filtrar por
_idna 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 porEcomSearch.setProductIds(), e ele monta{terms: {_id: [...]}}, essas vitrines voltam vazias — e somem sem erro, porque o template temv-if="items.length".Nas lojas Cloud Commerce isso está ativo hoje: o
vbeta-appdo@cloudcommerce/storefrontsetawindow.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
skuna v2 — 1 hit:Por
_idna v2 —total: 0:O mesmo
terms._idna v1 — funciona:Rodando a query completa do
RecommendedItems(comquantity > 0eavailable: true) sobre os IDs que a Graphs API devolve para um produto real: 4 produtos na v1, 0 na v2.Detalhe útil: a queryidsfunciona na v2. É sóterm/termssobre_idque não.Correção (editado): a query
idsNÃ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 paracommonFiltere montaterms._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 comproductIdsexplícito, que é comoTheAccount.html:73renderiza os favoritossrc/js/BuyTogether.js:157— compre juntosrc/js/TheProduct.js:493— composição de kitNenhum deles loga erro: o fetch resolve com zero itens e o
v-ifesconde a seção.Quem é afetado
vbeta-appaponta a busca para a v2."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
_elsda 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.TrocarInviável — a queryterms._idpor uma queryidsnosetProductIds.idsé ignorada pela v2 (ver correção acima e comentário abaixo). O caminho client-side viável é outro: rotear buscas por_idpelo?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.A opção 2 (revisada) foi entregue, mas a 1 continua valendo por três motivos: (a) busca por
_idcom aggregations — página de coleção com UI de filtros — segue quebrada na v2 mesmo com a PR, que só roteia queries semaggs; (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) e5d09191d24607a6a42d71361(Granola Low Carb,quantity: 184,available: true).Comportamentos a corrigir, por prioridade:
P1 —
term/termssobre_idno body retorna 0 hits. É o que quebra o caminho principal dosetProductIds. Critério de aceite:Esperado: 1 hit (o doc existe — trocando
_idporskuno mesmo filtro, ele volta). Hoje:total: 0.P2 — cláusulas não reconhecidas são descartadas silenciosamente (fail-open).
ids,match,query_string,bool.mustetermcom{value:}são ignorados e a busca devolve o catálogo inteiro. Para um consumidor comv-ifisso é vitrine vazia; para qualquer outro é resultado errado apresentado como certo. Critério de aceite: cláusula não suportada deve ou ser honrada ou retornar400— nunca ser removida da query.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:P4 — ranges e
sortno GET não funcionam.q=_id:X AND quantity:>0equantity:[1 TO *]retornam 0 mesmo com o doc tendoquantity: 184;&sort=price:descé ignorado (verificável comq=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_else 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.