JianghuJS集成ES实现检索

Elasticsearch

Elasticsearch(简称 ES)是一个开源的分布式全文搜索和分析引擎,主要用于处理大规模数据集的搜索、分析和可视化。它采用了分布式、多租户、实时性、高可用性和可扩展性等特点,适用于处理各种类型的结构化和非结构化数据,包括文本、数字、地理空间、时间序列等。

以下是 Elasticsearch 的一些优势:

  1. 高性能:Elasticsearch 是基于倒排索引(Inverted Index)的搜索引擎,具有极快的搜索和查询性能,能够在大规模数据集中实现高效的全文搜索和数据分析。
  2. 分布式和可扩展:Elasticsearch 支持分布式部署,可以通过添加或删除节点来实现水平扩展,从而处理大规模数据集和高并发请求。它还具有自动化的数据分片和副本机制,确保数据的高可用性和容错性。
  3. 多功能:Elasticsearch 提供了丰富的查询和分析功能,包括全文搜索、聚合、过滤、地理空间搜索、自动完成、关键字高亮、排序、分页等。同时,它还支持实时数据索引和搜索,能够满足各种复杂的搜索和分析需求。
  4. 易于使用和开发:Elasticsearch 提供了简单的 RESTful API,可以使用 HTTP 协议进行数据操作和查询。它还提供了丰富的客户端库,支持多种编程语言,使得开发者能够轻松地与 Elasticsearch 进行交互。
  5. 生态丰富:Elasticsearch 生态系统非常丰富,包括了各种插件和工具,用于数据导入、数据可视化、监控和管理等。此外,Elasticsearch 还与多个流行的开源工具和技术(如 Logstash、Kibana、Beats 等)紧密集成,形成了强大的 ELK(Elasticsearch、Logstash、Kibana)技术栈,用于实现日志管理、搜索和分析等应用场景。
  6. 可扩展的数据模型:Elasticsearch 允许灵活的数据模型,可以根据应用需求灵活地定义索引、类型和字段,支持复杂的数据结构和嵌套对象。同时,Elasticsearch 还支持动态字段映射,能够自动识别数据类型并进行索引,使得数据导入和查询更加灵活和便捷。

这些优势使得 Elasticsearch 成为了目前广泛应用于搜索、日志管理、数据分析、实时监控等领域的一种先进的搜索和分析引擎

江湖JS使用Elasticsearch

  1. 安装 Elasticsearch 客户端:在 江湖JS 项目中安装 @elastic/elasticsearch 模块。
    1. npm install @elastic/elasticsearch
  2. es统一配置:config/config.default.js
    1. elasticsearch: {
    2. node: 'http://127.0.0.1:9200',
    3. mingdingIndex: 'mingding',
    4. // 搜索字段及权重
    5. mingdingFieldWeight: [
    6. 'articleTitle^30',
    7. 'categoryName^20',
    8. 'articleTagList^10',
    9. 'articleContent',
    10. ],
    11. // 高权重文章 id
    12. mingdingHighWeightArticleIds: [],
    13. }
  3. 应用启用时挂载 Elasticsearch 客户端
    1. const elasticClient = require('@elastic/elasticsearch').Client;
    2. class AppBootHook {
    3. constructor(app) {
    4. this.app = app;
    5. }
    6. async didReady() {
    7. this.app.logger.info('连接 esClient', { node: this.app.config.elasticsearch.node });
    8. this.app.esClient = new elasticClient({
    9. node: this.app.config.elasticsearch.node,
    10. });
    11. }
    12. }
  4. es搜索
    1. // ES 搜索
    2. async esSearch(index, esRequestBody) {
    3. let result;
    4. try {
    5. result = await this.app.esClient.search({
    6. index,
    7. body: esRequestBody,
    8. });
    9. } catch (error) {
    10. this.logger.error('[ArticleInfoService] 搜索请求失败', { index, esRequestBody, error });
    11. this.logger.warn(`搜索请求失败, 原因:${error.message}`);
    12. return null;
    13. }
    14. // this.logger.info('[ElasticsearchService] 搜索 result', { index, esRequestBody, result, first: result.hits.hits[0] });
    15. this.logger.info('[ElasticsearchService] 搜索 result', { top5: result.hits.hits.slice(0, 5).map(o => _.pick(o, [ '_id', '_score' ])) });
    16. return result;
    17. }
    18. await this.esSearch(this.app.config.elasticsearch.mingdingIndex, {
    19. offset: 100,
    20. size: 10,
    21. query: {
    22. function_score: {
    23. query: {
    24. bool: {
    25. must: [
    26. {
    27. multi_match: {
    28. query: '知识的重要性',
    29. // 字段权重
    30. fields: [...],
    31. // 词条匹配度,
    32. tie_breaker: 0.3,
    33. },
    34. }, {
    35. // 过滤 articlePublishTime > now 的
    36. range: {
    37. articlePublishTime: {
    38. lt: dayjs().format(),
    39. },
    40. },
    41. },
    42. ],
    43. },
    44. },
    45. // 按条件加权
    46. functions: [...],
    47. // score_mode 可以控制如何将评分函数的结果合并到文档的评分中。它有以下几种模式:
    48. // multiply:将评分函数的结果与文档的原始评分相乘。这是默认的 score_mode 模式,适用于需要保留原始评分的情况。
    49. // sum:将评分函数的结果与文档的原始评分相加。适用于需要将评分函数的结果与原始评分进行合并的情况。
    50. // avg:将评分函数的结果与文档的原始评分求平均值。适用于需要将评分函数的结果与原始评分进行平均的情况。
    51. // first:使用评分函数的第一个结果作为文档的新评分。适用于只需要一个评分函数的结果的情况。
    52. // max:使用评分函数的最大值作为文档的新评分。适用于需要使用评分函数中的最大值的情况。
    53. // min:使用评分函数的最小值作为文档的新评分。适用于需要使用评分函数中的最小值的情况。
    54. score_mode: 'sum',
    55. boost_mode: 'sum',
    56. },
    57. },
    58. });

这只是一个简单的示例,实际上 Egg.js 与 Elasticsearch 的交互可以更加复杂,包括查询文档、更新文档、删除文档、搜索文档等更多操作。您可以参考 Elasticsearch 的 Node.js 客户端文档官方文档