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 的绝大多数常见场景