h5打开以查看
一、核心概念与安装
1. 官方客户端
Elasticsearch 官方提供了 @elastic/elasticsearch
Node.js 客户端,这是目前最推荐、最权威的库。
2. 安装
使用 npm 或 yarn 进行安装:
bash
npm install @elastic/elasticsearch # 或 yarn add @elastic/elasticsearch
二、连接 Elasticsearch 客户端
你需要获取 Elasticsearch 集群的地址和认证信息(如果启用了安全特性)来创建客户端实例。
基本连接(无安全认证)
javascript
const { Client } = require('@elastic/elasticsearch'); const client = new Client({ node: 'http://localhost:9200', // ES 节点的地址,默认端口是 9200 // 如果集群有多个节点,可以放入一个数组 // nodes: ['http://node1:9200', 'http://node2:9200'], }); // 测试连接 async function checkConnection() { try { const health = await client.cluster.health(); console.log('Elasticsearch 集群健康状态:', health.status); } catch (error) { console.error('连接 Elasticsearch 失败:', error.message); } } checkConnection();
带安全认证的连接(API Key/用户名密码/Cloud ID)
使用 API Key (推荐)
javascript
const client = new Client({ node: 'https://your-es-cluster.com:9200', auth: { apiKey: 'your-base64-encoded-api-key' // 例如: 'a2V5LWlkOmFwaS1rZXk=' } });
使用用户名和密码
javascript
const client = new Client({ node: 'https://your-es-cluster.com:9200', auth: { username: 'elastic', // 或其他用户名 password: 'your-password' } });
连接 Elastic Cloud
javascript
const client = new Client({ cloud: { id: 'your-cloud-id-from-elastic-cloud', }, auth: { username: 'elastic', password: 'your-password' } });
三、基本操作 (CRUD)
我们以一个 products
索引为例,文档类型为 _doc
。
1. 创建索引 (Create Index)
通常不需要手动创建,在插入第一条数据时会自动创建。但也可以显式创建以指定映射。
javascript
async function createIndex() { await client.indices.create({ index: 'products', body: { mappings: { properties: { name: { type: 'text' }, price: { type: 'float' }, description: { type: 'text' }, createdAt: { type: 'date' } } } } }); console.log('索引创建成功'); } // createIndex().catch(console.error);
2. 索引文档 (Index - Create/Replace)
index
方法会自动创建或全量替换文档。如果指定 id
已存在,则替换。
javascript
async function indexProduct() { const response = await client.index({ index: 'products', id: '1', // 如果不指定 id,ES 会自动生成一个 body: { name: 'iPhone 13', price: 799.99, description: 'A great phone from Apple.', createdAt: new Date() } }); console.log('文档索引成功:', response.body._id); } // indexProduct().catch(console.error);
3. 创建文档 (Create - 必须不存在)
create
方法要求文档 ID 必须不存在,否则会失败。
javascript
async function createProduct() { const response = await client.create({ index: 'products', id: '2', // 如果 id=2 已存在,此操作会报错 body: { name: 'Samsung Galaxy', price: 699.99, description: 'A powerful Android phone.' } }); console.log('文档创建成功:', response.body._id); }
4. 读取文档 (Read)
javascript
async function getProduct() { try { const response = await client.get({ index: 'products', id: '1' }); console.log('找到文档:', response.body._source); } catch (error) { if (error.meta.statusCode === 404) { console.log('文档不存在'); } else { throw error; } } } // getProduct().catch(console.error);
5. 更新文档 (Update)
使用 update
进行部分更新,性能更好。
javascript
async function updateProduct() { const response = await client.update({ index: 'products', id: '1', body: { doc: { // 要更新的字段放在 `doc` 里 price: 749.99 // 只更新价格字段 } } }); console.log('文档更新成功'); } // updateProduct().catch(console.error);
6. 删除文档 (Delete)
javascript
async function deleteProduct() { const response = await client.delete({ index: 'products', id: '2' }); console.log('文档删除成功'); } // deleteProduct().catch(console.error);
四、搜索操作 (Search)
这是 Elasticsearch 最强大的功能。
1. 简单搜索 (Match Query)
javascript
async function searchProducts() { const response = await client.search({ index: 'products', body: { query: { match: { name: 'iPhone' // 在 `name` 字段中搜索 "iPhone" } }, // 高亮显示匹配内容 highlight: { fields: { name: {} } }, // 排序 sort: [ { price: { order: 'desc' } } ], // 分页 from: 0, size: 10 } }); console.log(`共找到 ${response.body.hits.total.value} 条结果:`); response.body.hits.hits.forEach(hit => { console.log(`- ${hit._source.name} ($${hit._source.price})`); // 如果有高亮结果 if (hit.highlight) { console.log(' 高亮:', hit.highlight.name); } }); } // searchProducts().catch(console.error);
2. 布尔搜索 (Bool Query)
组合多个查询条件(must=AND, should=OR, must_not=NOT)。
javascript
async function boolSearch() { const response = await client.search({ index: 'products', body: { query: { bool: { must: [ // 必须同时满足 { match: { description: 'phone' } } ], filter: [ // 过滤,不贡献得分 { range: { price: { gte: 500, lte: 800 } } } ], must_not: [ // 必须不满足 { match: { name: 'Samsung' } } ] } } } }); // ... 处理结果 }
3. 聚合分析 (Aggregations)
javascript
async function runAggregation() { const response = await client.search({ index: 'products', body: { aggs: { // 定义聚合 avg_price: { // 平均价格聚合 avg: { field: 'price' } }, price_ranges: { // 范围聚合 range: { field: 'price', ranges: [ { to: 500 }, { from: 500, to: 800 }, { from: 800 } ] } } }, size: 0 // 不返回原始命中结果,只返回聚合结果 } }); console.log('平均价格:', response.body.aggregations.avg_price.value); console.log('价格分布:', response.body.aggregations.price_ranges.buckets); } // runAggregation().catch(console.error);
五、批量操作 (Bulk API)
对于大量数据的导入或更新,使用 Bulk API 可以极大提升效率。
javascript
async function bulkIndex() { const body = []; const dataset = [ { id: 100, name: 'Product A', price: 100 }, { id: 101, name: 'Product B', price: 200 }, // ... 更多数据 ]; // 构建 Bulk 请求体 dataset.forEach(doc => { body.push({ index: { _index: 'products', _id: doc.id } }); // 操作定义 body.push(doc); // 文档源数据 }); const { body: bulkResponse } = await client.bulk({ body, refresh: true }); if (bulkResponse.errors) { console.error('批量操作中有错误:', bulkResponse.errors); } else { console.log('批量操作成功'); } } // bulkIndex().catch(console.error);
六、最佳实践与错误处理
单例模式: 在整个应用中,通常只需要一个 Elasticsearch 客户端实例。请重用这个实例。
异步/await: 客户端所有 API 都返回 Promise,强烈建议使用
async/await
或.then().catch()
处理。错误处理: 一定要用
try...catch
包裹操作,并检查错误状态码。关闭连接: 在应用退出时,优雅地关闭客户端。
javascript
// 例如,在 Express 应用关闭时 process.on('SIGTERM', async () => { await client.close(); process.exit(0); });
使用最新版本: 确保客户端版本与 Elasticsearch 服务器版本兼容(通常主版本号相同即可,如 8.x 客户端连接 8.x 服务端)。
这份指南涵盖了 Node.js 操作 Elasticsearch 的绝大多数常见场景