Cliente Elasticsearch para TypeScript (@elastic/elasticsearch)
\n\nNo desenvolvimento web moderno, a busca em texto completo e a análise de dados tornaram-se partes essenciais de muitas aplicações. Elasticsearch é um poderoso sistema de busca distribuído, construído sobre o Apache Lucene. Para trabalhar com ele a partir de aplicações TypeScript (tanto no servidor Node.js quanto no navegador), utiliza-se o cliente oficial @elastic/elasticsearch. Neste artigo, abordaremos detalhadamente sua instalação, configuração e principais funcionalidades.
O que é @elastic/elasticsearch?
\n\n@elastic/elasticsearch é o cliente oficial de alto desempenho para Elasticsearch, escrito em TypeScript. Ele fornece um conjunto completo de APIs para interagir com o cluster Elasticsearch, incluindo:
- \n
- Indexação e exclusão de documentos \n
- Busca em texto completo com suporte a consultas complexas \n
- Agregações para análise de dados (agrupamento, estatísticas) \n
- Gerenciamento de índices e mapeamentos \n
- Suporte a pool de conexões, novas tentativas e balanceamento de carga \n
Graças ao suporte completo ao TypeScript, você obtém autocompletar, verificação de tipos e documentação diretamente na IDE.
\n\nInstalação
\n\nPara começar, instale o pacote via npm ou yarn:
\n\nnpm install @elastic/elasticsearch\n# ou\nyarn add @elastic/elasticsearch\n\nSe você usa TypeScript, não é necessário instalar tipos adicionais — eles já estão embutidos no pacote.
\n\nConexão e configuração do cliente
\n\nCrie uma instância do cliente informando a URL do seu cluster Elasticsearch:
\n\nimport { Client } from '@elastic/elasticsearch';\n\nconst client = new Client({\n node: 'http://localhost:9200', // ou endpoint na nuvem\n auth: {\n username: 'elastic',\n password: 'changeme'\n },\n // Para produção, recomenda-se usar TLS\n tls: {\n rejectUnauthorized: false // apenas para desenvolvimento!\n }\n});\n\nPara implantações em nuvem (Elastic Cloud), use cloud.id e auth.apiKey:
const client = new Client({\n cloud: {\n id: 'my-cluster:dXMtZWFzdD...'\n },\n auth: {\n apiKey: 'base64EncodedApiKey'\n }\n});\n\nOperações principais
\n\n1. Indexação de documento
\n\nAdicionando um novo documento a um índice:
\n\ninterface Product {\n id: number;\n name: string;\n description: string;\n price: number;\n tags: string[];\n}\n\nasync function indexProduct(product: Product) {\n const response = await client.index({\n index: 'products',\n id: String(product.id),\n body: product,\n refresh: 'wait_for' // aguardar a atualização do índice\n });\n console.log('Document indexed:', response.result);\n}\n\nindexProduct({\n id: 1,\n name: 'Notebook Lenovo ThinkPad',\n description: 'Notebook potente para desenvolvimento',\n price: 1200,\n tags: ['eletrônicos', 'notebooks']\n});\n\n2. Busca de documentos
\n\nBusca simples em texto completo pelo campo description:
async function searchProducts(query: string) {\n const response = await client.search({\n index: 'products',\n body: {\n query: {\n match: {\n description: query\n }\n },\n // Paginação\n from: 0,\n size: 10\n }\n });\n\n const hits = response.hits.hits.map(hit => hit._source);\n console.log('Found products:', hits);\n return hits;\n}\n\nsearchProducts('notebook desenvolvimento');\n\n3. Agregações
\n\nAgrupando produtos por tags:
\n\nasync function aggregateByTags() {\n const response = await client.search({\n index: 'products',\n body: {\n size: 0, // não retorna os próprios documentos\n aggs: {\n by_tag: {\n terms: {\n field: 'tags.keyword',\n size: 20\n }\n }\n