JianghuJS集成ES实现检索
Elasticsearch
Elasticsearch(简称 ES)是一个开源的分布式全文搜索和分析引擎,主要用于处理大规模数据集的搜索、分析和可视化。它采用了分布式、多租户、实时性、高可用性和可扩展性等特点,适用于处理各种类型的结构化和非结构化数据,包括文本、数字、地理空间、时间序列等。
以下是 Elasticsearch 的一些优势:
- 高性能:Elasticsearch 是基于倒排索引(Inverted Index)的搜索引擎,具有极快的搜索和查询性能,能够在大规模数据集中实现高效的全文搜索和数据分析。
- 分布式和可扩展:Elasticsearch 支持分布式部署,可以通过添加或删除节点来实现水平扩展,从而处理大规模数据集和高并发请求。它还具有自动化的数据分片和副本机制,确保数据的高可用性和容错性。
- 多功能:Elasticsearch 提供了丰富的查询和分析功能,包括全文搜索、聚合、过滤、地理空间搜索、自动完成、关键字高亮、排序、分页等。同时,它还支持实时数据索引和搜索,能够满足各种复杂的搜索和分析需求。
- 易于使用和开发:Elasticsearch 提供了简单的 RESTful API,可以使用 HTTP 协议进行数据操作和查询。它还提供了丰富的客户端库,支持多种编程语言,使得开发者能够轻松地与 Elasticsearch 进行交互。
- 生态丰富:Elasticsearch 生态系统非常丰富,包括了各种插件和工具,用于数据导入、数据可视化、监控和管理等。此外,Elasticsearch 还与多个流行的开源工具和技术(如 Logstash、Kibana、Beats 等)紧密集成,形成了强大的 ELK(Elasticsearch、Logstash、Kibana)技术栈,用于实现日志管理、搜索和分析等应用场景。
- 可扩展的数据模型:Elasticsearch 允许灵活的数据模型,可以根据应用需求灵活地定义索引、类型和字段,支持复杂的数据结构和嵌套对象。同时,Elasticsearch 还支持动态字段映射,能够自动识别数据类型并进行索引,使得数据导入和查询更加灵活和便捷。
这些优势使得 Elasticsearch 成为了目前广泛应用于搜索、日志管理、数据分析、实时监控等领域的一种先进的搜索和分析引擎
江湖JS使用Elasticsearch
- 安装 Elasticsearch 客户端:在 江湖JS 项目中安装 @elastic/elasticsearch 模块。
npm install @elastic/elasticsearch
- es统一配置:
config/config.default.js
elasticsearch: {
node: 'http://127.0.0.1:9200',
mingdingIndex: 'mingding',
// 搜索字段及权重
mingdingFieldWeight: [
'articleTitle^30',
'categoryName^20',
'articleTagList^10',
'articleContent',
],
// 高权重文章 id
mingdingHighWeightArticleIds: [],
}
- 应用启用时挂载 Elasticsearch 客户端
const elasticClient = require('@elastic/elasticsearch').Client;
class AppBootHook {
constructor(app) {
this.app = app;
}
async didReady() {
this.app.logger.info('连接 esClient', { node: this.app.config.elasticsearch.node });
this.app.esClient = new elasticClient({
node: this.app.config.elasticsearch.node,
});
}
}
- es搜索
// ES 搜索
async esSearch(index, esRequestBody) {
let result;
try {
result = await this.app.esClient.search({
index,
body: esRequestBody,
});
} catch (error) {
this.logger.error('[ArticleInfoService] 搜索请求失败', { index, esRequestBody, error });
this.logger.warn(`搜索请求失败, 原因:${error.message}`);
return null;
}
// this.logger.info('[ElasticsearchService] 搜索 result', { index, esRequestBody, result, first: result.hits.hits[0] });
this.logger.info('[ElasticsearchService] 搜索 result', { top5: result.hits.hits.slice(0, 5).map(o => _.pick(o, [ '_id', '_score' ])) });
return result;
}
await this.esSearch(this.app.config.elasticsearch.mingdingIndex, {
offset: 100,
size: 10,
query: {
function_score: {
query: {
bool: {
must: [
{
multi_match: {
query: '知识的重要性',
// 字段权重
fields: [...],
// 词条匹配度,
tie_breaker: 0.3,
},
}, {
// 过滤 articlePublishTime > now 的
range: {
articlePublishTime: {
lt: dayjs().format(),
},
},
},
],
},
},
// 按条件加权
functions: [...],
// score_mode 可以控制如何将评分函数的结果合并到文档的评分中。它有以下几种模式:
// multiply:将评分函数的结果与文档的原始评分相乘。这是默认的 score_mode 模式,适用于需要保留原始评分的情况。
// sum:将评分函数的结果与文档的原始评分相加。适用于需要将评分函数的结果与原始评分进行合并的情况。
// avg:将评分函数的结果与文档的原始评分求平均值。适用于需要将评分函数的结果与原始评分进行平均的情况。
// first:使用评分函数的第一个结果作为文档的新评分。适用于只需要一个评分函数的结果的情况。
// max:使用评分函数的最大值作为文档的新评分。适用于需要使用评分函数中的最大值的情况。
// min:使用评分函数的最小值作为文档的新评分。适用于需要使用评分函数中的最小值的情况。
score_mode: 'sum',
boost_mode: 'sum',
},
},
});
这只是一个简单的示例,实际上 Egg.js 与 Elasticsearch 的交互可以更加复杂,包括查询文档、更新文档、删除文档、搜索文档等更多操作。您可以参考 Elasticsearch 的 Node.js 客户端文档官方文档