一文搞懂 Elasticsearch 分布式搜索&分析引擎

一. Elasticsearch 概述

Elasticsearch 的定义和背景

Elasticsearch是一个开源的分布式搜索和分析引擎,用于存储、搜索和分析大量的数据。它构建在Apache Lucene库之上,提供了简单易用的RESTful API和丰富的查询语言,使用户可以轻松地进行实时数据索引、搜索和分析。

Elasticsearch的背景可以追溯到2010年,由Elastic公司(前称为Elasticsearch BV)创立,旨在解决传统关系型数据库无法处理海量数据和实时搜索的问题。它最初是作为全文搜索引擎的扩展功能而开发的,并迅速发展成为一种强大的分布式数据存储和分析解决方案。

Elasticsearch采用分布式架构,可以将数据分散存储在多个节点上,以实现高可用性和扩展性。它使用倒排索引技术来加速搜索过程,通过将每个唯一词项与包含该词项的文档关联起来,快速定位相关文档。同时,Elasticsearch还支持复杂的查询和聚合操作,如全文搜索、地理空间搜索、过滤器、排序、分组和统计等,使用户能够灵活地进行数据分析和挖掘。

除了强大的搜索和分析功能,Elasticsearch还具有以下特点:

  1. 实时性: Elasticsearch可以在数据写入后几乎立即对其进行索引和搜索,支持实时数据分析和监控。

  2. 可扩展性: 用户可以轻松地水平扩展Elasticsearch集群,通过添加更多的节点来处理大规模数据和高并发请求。

  3. 多种数据类型支持: Elasticsearch可以处理各种类型的数据,包括结构化数据、半结构化数据和非结构化数据。

  4. 强大的查询语言: Elasticsearch提供了丰富的查询语言,如全文查询、词项查询、范围查询、布尔查询等,支持复杂的条件和聚合操作。

  5. 易于集成: Elasticsearch与许多常见的数据存储和处理工具集成紧密,如Logstash(数据收集和转换)、Beats(数据采集)、Kibana(数据可视化)等。

由于其出色的性能和灵活性,Elasticsearch已经广泛用于各种应用场景,包括日志分析、实时监控、企业搜索、电子商务、安全分析、数据挖掘等。它被许多大型企业和组织采用,并成为当前最受欢迎的开源搜索和分析引擎之一。

Elasticsearch 的主要用途和特点

主要用途:
  1. 搜索引擎:Elasticsearch提供强大的全文搜索功能,可以快速索引和搜索大量的结构化、半结构化和非结构化数据。它支持各种查询类型和复杂的搜索条件,满足实时搜索的需求。

  2. 日志和事件数据分析:Elasticsearch被广泛用于日志管理和分析。它能够接收和索引来自不同来源的日志数据,并支持实时的日志搜索和分析。通过使用Elastic Stack中的其他组件(如Logstash和Kibana),用户可以构建完整的日志分析解决方案。

  3. 实时监控和指标分析:Elasticsearch可以用于实时监控和分析系统的性能指标、日志和事件数据。它可以接收并索引来自多个来源的指标数据,并提供实时的仪表盘和可视化工具,帮助用户实时了解系统状态和性能。

  4. 企业搜索:Elasticsearch被广泛应用于企业搜索场景,如产品目录搜索、文档搜索和电子邮件搜索等。它可以处理大规模的文本数据集,并提供高效的全文搜索、自动完成和相关性排序等功能。

  5. 数据分析和挖掘:Elasticsearch支持各种聚合操作,如统计、分组、排序和桶分析等。这使得用户可以从大规模数据集中提取有价值的信息,进行深入的数据分析和挖掘。

主要特点:
  1. 分布式架构:Elasticsearch采用分布式架构,可以处理大规模数据和高并发请求。它将数据分散存储在多个节点上,并提供数据冗余备份,以实现高可用性和扩展性。

  2. 实时性:Elasticsearch支持实时索引和查询数据,可以几乎立即对写入的数据进行索引和搜索。这使得用户可以快速获得最新的数据结果,并进行实时监控和决策。

  3. 强大的查询语言:Elasticsearch提供丰富的查询语言,包括全文查询、词项查询、范围查询、布尔查询等。用户可以通过灵活的查询条件和过滤器来获取精确的搜索结果。

  4. 多样化的数据类型支持:Elasticsearch可以处理各种类型的数据,包括结构化数据、半结构化数据和非结构化数据。它能够自动推断字段类型,并提供相应的索引和搜索功能。

  5. 易于集成和扩展:Elasticsearch与许多常见的数据存储和处理工具紧密集成,如Logstash、Beats和Kibana。它还提供了灵活的RESTful API,方便与其他应用程序进行集成和扩展。

  6. 开源和活跃的社区支持:Elasticsearch是一个开源项目,拥有庞大的开发者社区。这意味着用户可以从社区中获取丰富的资源、文档和支持,并参与到项目的发展和改进中。

二. 基本概念和核心组件

索引、文档、类型等基础概念

  1. 索引(Index)

    • 索引是 Elasticsearch 中最顶层的数据容器,用于组织和存储相关的文档。
    • 索引由一个或多个分片(Shard)组成,每个分片是一组独立的文档集合。
    • 每个索引都有一个唯一的名称,用于在搜索和操作过程中引用它。

    操作演示:

    • 创建一个名为 “my-index” 的索引:
      PUT /my-index
      
  2. 文档(Document)

    • 文档是 Elasticsearch 中的基本数据单元,以 JSON 格式表示,类似于传统数据库中的行。
    • 文档是与索引相关联的实际数据,可以是任何形式的信息。
    • 每个文档都有一个唯一的 ID 来标识自己,并属于特定的索引。

    操作演示:

    • 在 “my-index” 索引中创建一个 ID 为 “1” 的文档:
      POST /my-index/_doc/1
      {
        "title": "Elasticsearch 介绍",
        "content": "Elasticsearch 是一个开源的分布式搜索引擎,用于高效地存储、检索和分析数据。",
        "timestamp": "2023-06-29T00:00:00"
      }
      
  3. 类型(Type)

    • 在 Elasticsearch 7.x 版本之前,一个索引可以包含多个类型。类型是索引内部的逻辑分类,用于将文档按照某种方式分组。
    • 每个类型都有自己的映射(Mapping),它定义了每个字段的数据类型、分析器和其他属性。

    操作演示:

    • 创建一个名为 “my-index” 的索引,并定义一个名为 “product” 的类型:

      PUT /my-index
      {
        "mappings": {
          "product": {
            "properties": {
              "name": { "type": "text" },
              "price": { "type": "float" }
            }
          }
        }
      }
      
    • 在 “my-index” 索引的 “product” 类型中创建一个名为 “1” 的文档:

      PUT /my-index/product/1
      {
        "name": "iPhone",
        "price": 999.99
      }
      

从 Elasticsearch 7.x 版本开始,类型逐渐被废弃,推荐将数据以更细粒度的索引方式进行组织。

集群、节点和分片的概念及其作用

  1. Elasticsearch 集群

    • Elasticsearch 集群是由一个或多个节点组成的集合。它具有分布式特性,可以将数据分布在多个节点上,从而实现高可用性和扩展性。
    • 集群中的每个节点都知道整个集群的状态,并可以接收和处理请求。节点之间通过内部通信来协调数据的分布和复制。
  2. Elasticsearch 节点

    • 节点是构成 Elasticsearch 集群的基本单元。一个节点可以是一台物理服务器或虚拟机。
    • 在集群中,每个节点都有一个唯一的名称,并且扮演着特定的角色,如主节点、数据节点或协调节点等。
    • 主节点负责集群级别的管理和维护,协调节点负责请求路由,而数据节点存储和处理数据。
  3. Elasticsearch 分片

    • 分片是索引中数据的逻辑划分单元。每个索引可以被分成多个分片,分布在集群中的不同节点上。
    • 分片是 Elasticsearch 实现高扩展性和水平分布式存储的关键。它允许数据在集群中分布存储,并提供并行处理能力。
    • 每个分片本身就是一个完整的、独立的索引,具有自己的倒排索引、文档和对应的搜索服务。

    分片包括两种类型:

    • 主分片(Primary Shard):每个文档都被分配到一个主分片上,主分片负责文档的增删改操作。
    • 副本分片(Replica Shard):主分片的副本,用于提供冗余和高可用性。副本分片负责读操作,可以在主分片不可用时接管。

    注意事项:

    • 分片的数量在索引创建时定义,并且一旦创建后不能更改。
    • 在决定分片数量时,需要考虑集群的大小、硬件资源以及数据量等因素。

主分片和副本分片的使用和配置方法

  1. 主分片(Primary Shard):

    • 主分片负责索引中文档的增删改操作。
    • 每个文档都会被分配到一个主分片上,主分片根据文档的 ID 进行哈希计算,并将文档存储在相应的主分片上。
    • 索引中的每个主分片都是一个独立的、完整的 Lucene 索引。

    配置方法:

    • 在创建索引时,可以通过设置参数 "number_of_shards" 来定义主分片的数量。
    • 例如,创建一个具有 5 个主分片的索引:
      PUT /my-index
      {
        "settings": {
          "number_of_shards": 5
        },
        "mappings": {
          ...
        }
      }
      
  2. 副本分片(Replica Shard):

    • 副本分片是主分片的复制品,用于提供冗余和高可用性。副本分片也可以处理读操作,以支持更好的并发性和负载均衡。
    • 当主分片不可用时,副本分片可以接替成为新的主分片,并确保数据的可访问性和持久性。
    • 副本分片还允许在集群中的多个节点上并行地处理搜索请求。

    配置方法:

    • 在创建索引时,可以通过设置参数 "number_of_replicas" 来定义副本分片的数量。

    • 例如,创建一个具有 1 个副本分片的索引:

      PUT /my-index
      {
        "settings": {
          "number_of_shards": 3,
          "number_of_replicas": 1
        },
        "mappings": {
          ...
        }
      }
      
    • 可以动态调整索引的副本分片数量。例如,将索引的副本分片数量增加到 2:

      PUT /my-index/_settings
      {
        "index": {
          "number_of_replicas": 2
        }
      }
      

主分片和副本分片在 Elasticsearch 中起到不同的作用。主分片负责索引的写操作,而副本分片提供冗余、高可用性和读操作的支持。您可以在索引创建或动态修改过程中设置主分片和副本分片的数量,以满足您的需求。

三、搜索

搜索的基本原理

Elasticsearch 是将搜索请求发送到整个集群中的各个节点,并通过倒排索引来快速找到匹配的文档。

  1. 倒排索引(Inverted Index):

    • Elasticsearch 使用倒排索引来加速搜索。倒排索引是一个将每个词与包含该词的文档关联起来的数据结构。
    • 它是通过将文档中的每个词抽取出来,然后记录该词出现在哪些文档中来构建的。
    • 以词为基础构建索引,而不是以文档为基础进行搜索,这使得 Elasticsearch 可以在大量文档中进行高效的全文搜索。
  2. 分词器(Tokenizer)和分析器(Analyzer):

    • 在构建倒排索引之前,Elasticsearch 使用分词器对文本进行处理,将其切分成一个个的词(term)。
    • 分析器是由分词器、字符过滤器和标记过滤器组成的一个处理链。
    • 分词器将文本切分成单个的词,字符过滤器对词进行预处理(如去除标点符号、转换大小写等),标记过滤器对词进行进一步处理(如同义词替换、词干提取等)。
  3. 查询解析和查询语句:

    • 在搜索请求中,Elasticsearch 接收到查询字符串并进行解析。
    • Elasticsearch 支持多种类型的查询,如全文查询、精确值查询、范围查询等。
    • 查询解析过程将查询字符串转换为内部的查询对象,然后与倒排索引进行匹配。
  4. 倒排索引的匹配和评分:

    • 当查询被解析后,Elasticsearch 将查询与倒排索引进行匹配。
    • 倒排索引会快速找到包含查询中的词的文档,并生成初始的匹配结果集。
    • 这些匹配结果都带有分数(score),用于衡量文档与查询的相关性。
  5. 结果排序和高亮显示:

    • Elasticsearch 可以根据匹配文档的相关性对搜索结果进行排序。
    • 通过给每个文档计算一个得分来提供排序依据,得分通常基于词频、字段长度、查询权重等因素。
    • 此外,Elasticsearch 还支持在搜索结果中高亮显示查询的关键字,以便更好地展示匹配部分。
  6. 分布式搜索:

    • Elasticsearch 是一个分布式搜索引擎,可以水平扩展以处理大规模数据。
    • 当进行搜索时,查询将被分发到整个集群中的各个节点,并行地执行查询操作。
    • 每个节点在本地返回局部的匹配结果,然后由协调节点(coordinator)将这些结果进行合并和排序,最后返回给用户。

Elasticsearch 能够快速而高效地进行全文搜索,并提供准确的搜索结果。对于大规模和复杂的数据集,它的搜索能力得到了有效的优化和扩展。

如何构建查询语句

构建查询语句是使用 Elasticsearch 进行搜索的关键步骤之一。通过构建准确和灵活的查询语句,可以获得符合需求的搜索结果。

  1. 查询类型选择:

    • Elasticsearch 提供了多种查询类型,例如全文查询、精确值查询、范围查询等。根据需求选择合适的查询类型。
  2. 构建查询条件:

    • 查询条件是指要在搜索中匹配的规则和限制。它们由 JSON 组成,可以包含多个字段和操作符。
    • 常见的字段包括索引、类型、文档属性和字段等。操作符用于确定搜索的逻辑关系,如匹配、不匹配、范围等。
  3. 使用查询字符串(Query String):

    • Elasticsearch 提供了一种简化的查询方式,即查询字符串。它允许您以人类可读的方式构建查询,而不需要编写复杂的 JSON 查询语句。
    • 查询字符串可以包含字段名、关键词、布尔运算符和通配符等。
  4. 使用 Query DSL:

    • 如果需要更复杂和灵活的查询,可以使用 Elasticsearch 的 Query DSL(Domain Specific Language)。
    • Query DSL 是 Elasticsearch 提供的一种强大而灵活的查询语法,可以根据具体需求构建复杂的查询结构。
    • Query DSL 使用 JSON 对象来表示查询,可以包含各种查询类型、过滤器、聚合等。
  5. 添加过滤器(Filters):

    • 过滤器用于进一步限制搜索结果,以筛选出满足特定条件的文档。
    • 过滤器可以与查询结合使用,也可以单独使用。它们可以根据字段的值进行匹配或排除。
  6. 使用聚合(Aggregations):

    • Elasticsearch 的聚合功能可以对搜索结果进行分组、统计和计算。
    • 通过聚合,可以获得关于数据集的更深入的洞察,并生成各种统计指标,如平均值、最大值、最小值等。
  7. 调整查询参数:

    • Elasticsearch 允许您调整查询的各种参数,以控制搜索的行为和性能。
    • 例如,您可以设置返回结果的数量、排序规则、分页设置、超时时间等。
示例
  1. 全文查询(Match Query):

    • 查询特定字段中包含指定关键词的文档。
    {
      "query": {
        "match": {
          "title": "Elasticsearch"
        }
      }
    }
    
  2. 精确值查询(Term Query):

    • 查询特定字段中精确匹配指定值的文档。
    {
      "query": {
        "term": {
          "category": "Technology"
        }
      }
    }
    
  3. 范围查询(Range Query):

    • 查询特定字段中落在指定范围内的文档。
    {
      "query": {
        "range": {
          "price": {
            "gte": 10,
            "lte": 100
          }
        }
      }
    }
    
  4. 布尔查询(Bool Query):

    • 组合多个子查询条件,使用逻辑运算符进行匹配。
    {
      "query": {
        "bool": {
          "must": [
            { "match": { "title": "Elasticsearch" } },
            { "term": { "category": "Technology" } }
          ],
          "must_not": { "term": { "status": "Archived" } }
        }
      }
    }
    
  5. 高亮显示查询结果:

    • 在查询结果中高亮显示匹配的关键词。
    {
      "query": {
        "match": {
          "content": "Elasticsearch"
        }
      },
      "highlight": {
        "fields": {
          "content": {}
        }
      }
    }
    

使用过滤器和聚合操作进行高级搜索

使用过滤器和聚合操作是进行高级搜索的重要手段。过滤器用于筛选搜索结果,而聚合操作用于分组、统计和计算搜索结果。

  1. 过滤器(Filters):

    • 过滤器用于根据特定条件来筛选文档,只返回满足条件的文档,而不会对得分进行影响。
    • 过滤器可以与查询结合使用,也可以单独使用。
    • 常见的过滤器类型包括:
      • Term Filter:匹配指定字段中精确匹配的值。
      • Range Filter:匹配指定字段中落在指定范围内的值。
      • Exists Filter:匹配指定字段存在的文档。
      • Bool Filter:根据多个子过滤器的逻辑关系进行匹配。
      • Geo Distance Filter:匹配指定字段中距离某一地理点一定范围内的值。
  2. 聚合操作(Aggregations):

    • 聚合操作用于在搜索结果上进行分组、统计和计算,从而获取更深入的洞察和统计指标。
    • 聚合操作基于搜索结果集进行操作,并返回计算后的结果。
    • 常见的聚合操作类型包括:
      • Terms Aggregation:根据指定字段的值进行分组,并统计每个分组的文档数或其他指标。
      • Range Aggregation:将指定字段的值划分为多个范围,并统计落在每个范围内的文档数或其他指标。
      • Date Histogram Aggregation:按照时间间隔对指定字段进行分组,并统计每个时间间隔内的文档数或其他指标。
      • Avg/Min/Max/Sum Aggregation:计算指定字段的平均值、最小值、最大值、总和等统计指标。
      • Nested/Reverse Nested Aggregation:用于处理嵌套的文档结构,并对嵌套字段进行聚合操作。

通过使用过滤器和聚合操作,可以实现更精确的搜索和更深入的数据分析。可以根据具体需求来选择合适的过滤器类型和聚合操作,并根据数据结构和索引映射来构建高级搜索查询语句。

示例
  1. 过滤器示例:
    假设我们有一个电商平台的商品索引,每个商品文档包含字段:title(商品标题)、price(价格)和 category(商品类别)。我们想要查询价格在 10 到 100 之间,并且类别为 “Technology” 的商品。
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "price": {
              "gte": 10,
              "lte": 100
            }
          }
        },
        {
          "term": {
            "category": "Technology"
          }
        }
      ]
    }
  }
}

在上述查询中,我们使用了 Bool 查询构造器来组合多个过滤器。range 过滤器用于筛选价格在指定范围内的商品,而 term 过滤器则用于筛选类别为 “Technology” 的商品。该查询返回的结果将只包含满足这两个条件的商品文档。

  1. 聚合操作示例:
    继续沿用上述的电商平台商品索引示例,现在我们想要统计不同类别的商品数量,并按照数量从高到低进行排序。
{
  "aggs": {
    "category_count": {
      "terms": {
        "field": "category",
        "size": 10,
        "order": {
          "_count": "desc"
        }
      }
    }
  }
}

在上述聚合操作中,我们使用了 Terms 聚合操作来按照 category 字段对商品进行分组,并计算每个分类的文档数量。size 参数指定了返回的分组数量上限,而 order 参数以文档数量 _count 字段的降序进行排序。该查询将返回按照商品类别分组后的结果,其中每个分组都包含类别和对应的商品数量。

四、映射和分析

映射的概念和作用

在 Elasticsearch 中,映射(Mapping)是用于定义文档如何存储和索引的过程。它决定了文档中的字段及其属性,例如数据类型、分词器、索引设置等。映射在建立索引之前定义,并且在索引过程中将其应用于文档,以便 Elasticsearch 能够正确地解析和处理文档的内容。

映射的作用包括:

  1. 定义字段类型:

    • 映射确定每个字段的数据类型,如字符串、数字、日期等。这对于搜索和排序是非常重要的,因为不同的数据类型具有不同的排序和比较方式。
    • 例如,一个字段可以定义为 text 类型,用于全文搜索,或者定义为 keyword 类型,用于精确匹配和聚合操作。
  2. 配置分词器:

    • 映射通过指定分词器来定义文本字段的文本处理方式,将文本拆分成独立的单词(术语)。
    • 分词器用于构建倒排索引,使得可以根据单词进行搜索,并实现全文搜索的功能。
    • 例如,可以为英文字段指定 standard 分词器,而为中文字段指定 smartcn 分词器。
  3. 索引控制:

    • 映射还允许配置字段是否需要被索引以及如何被索引。
    • 可以指定字段是否需要被全文索引(用于全文搜索)或者只需要被精确匹配索引(用于过滤器和聚合操作)。
    • 还可以配置索引设置,如分片数、副本数、刷新频率等。
  4. 动态映射:

    • Elasticsearch 支持自动检测并根据新文档的字段自动生成映射。这称为动态映射。
    • 动态映射根据字段值自动推断数据类型,并为其创建默认映射。
    • 可以通过预定义映射和显式映射来控制动态映射的行为,以确保正确的字段类型和属性被应用。

通过映射,我们可以灵活地定义文档结构和字段属性,以满足特定的搜索和分析需求。良好的映射设计可以提高搜索性能、减少存储空间,并确保数据的一致性和准确性。在建立索引之前,仔细考虑和定义映射是非常重要的。

示例

以下是一个示例,展示了如何定义一个映射来索引包含不同类型字段的文档:

PUT /my_index
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      },
      "price": {
        "type": "float"
      },
      "category": {
        "type": "keyword"
      },
      "description": {
        "type": "text",
        "analyzer": "english"
      },
      "created_at": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      }
    }
  }
}

在上述示例中:

  • 我们创建了一个名为 my_index 的索引,并指定了其映射。
  • properties 对象用于定义索引中的字段和其属性。
  • title 字段被定义为 text 类型,可以用于全文搜索。
  • price 字段被定义为 float 类型,可以用于数值排序和统计。
  • category 字段被定义为 keyword 类型,用于精确匹配和聚合操作。
  • description 字段被定义为 text 类型,并指定了分词器 english,用于英文文本的处理。
  • created_at 字段被定义为 date 类型,并指定了日期格式。

通过这样的映射定义,当我们索引文档时,Elasticsearch 将根据映射来解析和处理各个字段的内容,并构建适合搜索和分析的倒排索引结构。这使得我们可以使用各种查询和聚合操作来搜索、过滤和分析文档中的数据。

使用分析器进行文本处理和搜索优化

使用分析器是 Elasticsearch 中进行文本处理和搜索优化的关键步骤之一。分析器负责将文本转换为有意义的词条,以便能够进行有效的搜索和分析。

  1. 了解分析器的类型:
    Elasticsearch 提供了多种类型的分析器,每个分析器都有不同的用途和效果。

    • 标准分析器(Standard Analyzer):默认的分析器,适用于大多数场景,包括分割文本、删除停用词、小写化等。
    • 简单分析器(Simple Analyzer):根据非字母字符进行简单分割,不考虑大小写或停用词。
    • 语言分析器(Language Analyzer):针对特定语言设计的分析器,例如英语分析器(English Analyzer)或中文分析器(Chinese Analyzer)等。
    • 自定义分析器(Custom Analyzer):允许你根据具体需求自定义分析器的组合,可以包含多个分词器、过滤器等。
  2. 创建索引时定义分析器:
    在创建索引时,可以通过指定 mappings 字段来定义分析器。在字段的映射中,使用 analyzer 属性来指定要使用的分析器。

    {
      "mappings": {
        "properties": {
          "field_name": {
            "type": "text",
            "analyzer": "analyzer_name"
          },
          ...
        }
      }
    }
    
    • field_name:要应用分析器的字段名称。
    • type:字段类型,通常为 text
    • analyzer_name:要使用的分析器的名称。
  3. 动态映射和自动应用分析器:
    默认情况下,Elasticsearch 在创建索引时会根据字段的数据类型自动应用相应的分析器。例如,对于 text 类型的字段,将自动应用默认的标准分析器。这是通过动态映射实现的。

  4. 明确指定分析器:
    如果你想显式地指定要使用的分析器,可以在查询或索引文档时使用 _analyze API 来手动应用分析器。

    GET /my_index/_analyze
    {
      "analyzer": "analyzer_name",
      "text": "your_text_to_analyze"
    }
    
    • analyzer_name:要使用的分析器的名称。
    • your_text_to_analyze:要进行分析的文本。
  5. 分词器和过滤器:
    分析器由分词器(Tokenizer)和过滤器(Filter)组成。分词器负责将文本拆分成单独的词条,而过滤器则对词条进行进一步的处理,如删除停用词、词干提取、大小写转换等。

  6. 自定义分析器:
    如果预定义的分析器无法满足特定需求,你可以构建自定义分析器。自定义分析器可以包含一个或多个分词器和过滤器,以便根据需要进行文本处理。

  7. 查看分析结果:
    在使用分析器时,你可以使用 _analyze API 来查看分析结果,以确保分析器正常工作并生成预期的词条。

  8. 更新分析器:
    如果已经创建了索引,但想要更改字段的分析器,需要重新创建索引或使用 Elasticsearch 的 Reindex API 将文档从旧索引重新索引到新索引中。

通过使用适当的分析器和配置,可以实现更好的搜索效果和更准确的文本分析。请根据具体需求选择合适的分析器,并确保对分析结果进行验证和测试。

示例

假设我们有一个索引,用于存储产品信息,并且想要对产品的描述字段进行文本处理和搜索优化。我们将使用标准分析器来演示。

  1. 创建索引时定义分析器:
    我们可以在创建索引时为描述字段指定使用的分析器。

    PUT /products
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "type": "standard"
            }
          }
        }
      },
      "mappings": {
        "properties": {
          "description": {
            "type": "text",
            "analyzer": "my_analyzer"
          }
        }
      }
    }
    

    在上述示例中,我们定义了一个名为 my_analyzer 的标准分析器,并将其应用于 description 字段。

  2. 插入文档:
    现在,我们可以插入一些文档到 products 索引中,包含产品的描述信息。

    POST /products/_doc/1
    {
      "description": "这是一个高质量的耳机,具有优秀的音质和舒适的佩戴体验。"
    }
    
    POST /products/_doc/2
    {
      "description": "这款电视屏幕尺寸大,画质清晰逼真,适合观看电影和玩游戏。"
    }
    
  3. 搜索文档:
    现在,我们可以使用搜索查询来搜索具有特定关键字的产品描述。

    GET /products/_search
    {
      "query": {
        "match": {
          "description": "电视"
        }
      }
    }
    

    上述搜索查询将返回含有关键字 “电视” 的产品描述。

五、监控和日志

使用集群健康 API 监控集群状态

  1. API名称和端点:

    • API名称:集群健康API(Cluster Health API)
    • 端点:/_cluster/health
  2. 请求方法:

    • GET方法
  3. 请求参数:

    • level(可选):指定返回的健康级别,可以是下列之一:
      • cluster:返回整个集群的健康信息(默认)
      • indices:返回每个索引的健康信息
      • shards:返回每个分片的健康信息
    • wait_for_status(可选):等待集群达到指定状态后再返回响应,默认为green。可选的状态有:
      • green:所有主分片和副本分片都可用
      • yellow:所有主分片可用,但不是所有副本分片都可用
      • red:至少有一个主分片不可用
    • timeout(可选):设置等待状态的超时时间,默认为30秒。
    • master_timeout(可选):等待选择主节点的超时时间,默认为30秒。
  4. 响应结果:

    • cluster_name:集群名称
    • status:集群健康状态,可能的值有:
      • green:所有主分片和副本分片都可用
      • yellow:所有主分片可用,但不是所有副本分片都可用
      • red:至少有一个主分片不可用
    • timed_out:请求是否超时
    • number_of_nodes:集群中节点的数量
    • number_of_data_nodes:数据节点的数量
    • active_primary_shards:活动的主分片数量
    • active_shards:活动的分片数量(包括主分片和副本分片)
    • relocating_shards:正在迁移的分片数量
    • initializing_shards:正在初始化的分片数量
    • unassigned_shards:未分配的分片数量
    • delayed_unassigned_shards:延迟未分配的分片数量
    • number_of_pending_tasks:待处理的任务数量
    • number_of_in_flight_fetch:正在进行的取回操作数量
    • task_max_waiting_in_queue_millis:在队列中等待的最长任务时间(毫秒)
    • active_shards_percent_as_number:以百分比形式表示的活动分片比例
  5. 示例请求和响应:

    • 请求示例:GET /_cluster/health?level=indices
    • 响应示例:
      {
        "cluster_name": "my_cluster",
        "status": "green",
        "timed_out": false,
        "number_of_nodes": 5,
        "number_of_data_nodes": 3,
        "active_primary_shards": 10,
        "active_shards": 20,
        "relocating_shards": 0,
        "initializing_shards": 0,
        "unassigned_shards": 0,
        "delayed_unassigned_shards": 0,
        "number_of_pending_tasks": 0,
        "number_of_in_flight_fetch": 0,
        "task_max_waiting_in_queue_millis": 0,
        "active_shards_percent_as_number": 100.0
      }
      

通过使用集群健康API,您可以定期调用该API以获取关于集群的实时状态信息。这有助于监控集群运行状况、检测潜在问题并及时采取行动。您还可以基于集群健康的状态定义警报规则,以便在集群出现问题时及时通知负责人员。

配置和查看日志文件

  1. 配置日志文件:
    要配置日志文件,需要修改Elasticsearch的配置文件,该文件位于config目录下。默认情况下,配置文件名为elasticsearch.yml

    • 打开配置文件:使用文本编辑器打开elasticsearch.yml文件。
    • 配置日志级别:找到日志级别配置项,默认为info,可以根据需要更改为debugwarnerror等级别。
    • 配置日志输出位置:找到path.logs配置项,设置日志文件的输出路径。可以指定完整路径,或者使用相对于ES_HOME(Elasticsearch安装目录)的路径。
  2. 查看日志文件:
    日志文件位于指定的输出路径,默认为logs目录。您可以通过以下方式查看日志文件:

    • 使用命令行:在命令行中使用文本查看工具(如cattail等)来查看日志文件,例如:cat path/to/logfile.log
    • 使用图形界面工具:使用文件管理器或文本编辑器,打开日志文件查看其内容。
  3. 日志文件的类型:
    Elasticsearch生成多个日志文件,其中包括:

    • elasticsearch.log:主要日志文件,包含Elasticsearch的运行状态、异常和操作相关的信息。
    • gc.log:GC(垃圾回收)日志文件,记录了JVM的垃圾回收活动。
    • deprecation.log:包含关于使用已弃用功能的警告信息。
    • audit.log:若启用了审计功能,将记录审核事件的日志。
  4. 日志文件的轮转和归档:
    Elasticsearch支持日志文件的轮转和归档,以便管理和维护日志文件的大小和数量。可以使用第三方的日志轮转工具(如logrotate)来完成此任务,并在配置文件中指定轮转的规则和频率。

    例如,使用logrotate工具,在/etc/logrotate.d目录下创建一个名为elasticsearch的配置文件,并添加以下内容:

    /path/to/elasticsearch/logs/*.log {
        daily
        rotate 7
        compress
        delaycompress
        missingok
        notifempty
    }
    

    这将每天轮转一次日志文件,并保留最近的7个归档文件。

通过配置和查看日志文件,您可以及时获取Elasticsearch集群的运行状态、故障信息和性能问题,有助于排查和解决各种问题,并确保集群的顺利运行。

六、实际应用

电商平台的商品搜索和推荐

假设我们有一个电商平台,用户可以通过搜索框来搜索商品,并根据他们的行为历史和喜好,我们也希望能够向他们推荐相关的商品。

步骤1: 数据准备
首先,我们需要准备商品数据。假设我们有以下三个商品的数据:

  • 商品1:
    • 名称:iPhone 12
    • 描述:Apple 最新款智能手机
    • 价格:9999元
    • 品牌:Apple
    • 类别:手机
  • 商品2:
    • 名称:Samsung Galaxy S21
    • 描述:三星旗舰智能手机
    • 价格:8999元
    • 品牌:Samsung
    • 类别:手机
  • 商品3:
    • 名称:Sony WH-1000XM4
    • 描述:无线降噪耳机
    • 价格:1999元
    • 品牌:Sony
    • 类别:耳机

步骤2: 索引和映射设置
接下来,我们需要创建一个索引,并定义映射设置,以便Elasticsearch知道如何处理我们的商品数据。我们将使用Elasticsearch的Index API和Mapping API来完成这一步。

下面是一个使用CURL命令创建索引和定义映射的示例:

PUT /products
{
  "mappings": {
    "properties": {
      "name": {"type": "text"},
      "description": {"type": "text"},
      "price": {"type": "float"},
      "brand": {"type": "keyword"},
      "category": {"type": "keyword"}
    }
  }
}

在上述示例中,我们使用PUT请求创建了一个名为"products"的索引,并指定了每个字段的数据类型。

步骤3: 数据导入
接下来,我们将商品数据导入到Elasticsearch索引中。我们可以使用Elasticsearch的Index API来完成这一步。

下面是一个使用CURL命令将每个商品文档导入到"products"索引的示例:

POST /products/_doc/1
{
  "name": "iPhone 12",
  "description": "Apple 最新款智能手机",
  "price": 9999,
  "brand": "Apple",
  "category": "手机"
}

POST /products/_doc/2
{
  "name": "Samsung Galaxy S21",
  "description": "三星旗舰智能手机",
  "price": 8999,
  "brand": "Samsung",
  "category": "手机"
}

POST /products/_doc/3
{
  "name": "Sony WH-1000XM4",
  "description": "无线降噪耳机",
  "price": 1999,
  "brand": "Sony",
  "category": "耳机"
}

在上述示例中,我们使用POST请求将每个商品文档导入到"products"索引中,每个文档都有一个唯一的标识符(例如1、2、3)。

步骤4: 商品搜索接口
现在,我们准备好进行商品搜索。我们将使用Elasticsearch的Search API来执行搜索请求。

下面是一个使用CURL命令进行商品搜索的示例:

GET /products/_search
{
  "query": {
    "match": {
      "name": "iphone"
    }
  }
}

在上述示例中,我们使用GET请求执行了一个商品搜索请求,查询包含"iphone"关键字的商品名称。

步骤5: 查询构建和商品搜索
接下来,让我们使用Java代码来构建并执行相同的商品搜索请求。我们将使用Elasticsearch的Java High-Level REST Client来实现。

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;

public class ElasticsearchProductSearchExample {
    private static final String INDEX_NAME = "products";
    private static final String HOSTNAME = "localhost";
    private static final int PORT_NUMBER = 9200;

    public static void main(String[] args) {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost(HOSTNAME, PORT_NUMBER, "http")));

        try {
            // 构建商品搜索请求
            SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("name", "iphone");
            searchSourceBuilder.query(matchQuery);

            searchRequest.source(searchSourceBuilder);

            // 执行商品搜索请求
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

            // 处理商品搜索结果
            searchResponse.getHits().forEach(hit -> {
                System.out.println(hit.getSourceAsString());
            });
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述Java代码示例中,我们创建了一个RestHighLevelClient实例,并指定Elasticsearch主机的主机名和端口号。

我们使用SearchRequestSearchSourceBuilder来构建商品搜索请求。在商品搜索请求中,我们使用MatchQueryBuilder指定查询关键字并设置要在哪个字段上执行。

使用client.search方法来执行商品搜索请求,并使用SearchResponse处理搜索结果。

步骤6: 商品推荐接口
除了商品搜索,我们还希望能够向用户推荐相关的商品。为此,我们可以使用Elasticsearch的推荐功能。具体来说,我们可以使用基于用户历史行为的协同过滤推荐算法来推荐商品。

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;

public class ElasticsearchProductRecommendationExample {
    private static final String INDEX_NAME = "products";
    private static final String HOSTNAME = "localhost";
    private static final int PORT_NUMBER = 9200;

    public static void main(String[] args) {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost(HOSTNAME, PORT_NUMBER, "http")));

        try {
            // 构建商品推荐请求
            SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("category", "手机");
            searchSourceBuilder.query(matchQuery);
            searchSourceBuilder.size(5); // 限制结果数量为5个

            searchRequest.source(searchSourceBuilder);

            // 执行商品推荐请求
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

            // 处理商品推荐结果
            searchResponse.getHits().forEach(hit -> {
                System.out.println(hit.getSourceAsString());
            });
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述Java代码示例中,我们使用相同的步骤来创建和关闭RestHighLevelClient实例。

我们使用SearchRequestSearchSourceBuilder来构建商品推荐请求。在商品推荐请求中,我们使用MatchQueryBuilder指定查询的条件(例如商品类别为手机)。

此外,我们可以使用searchSourceBuilder.size方法限制结果数量,以便只返回若干个推荐商品。

使用client.search方法来执行商品推荐请求,并使用SearchResponse处理搜索结果。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Elasticsearch是一个基于开源的分布式搜索分析引擎,主要用于处理大规模数据的实时搜索分析和存储。它利用了分布式架构的优势,可以快速地搜索和处理海量数据。 Elasticsearch具有高度的可伸缩性,可以水平扩展以适应不断增长的数据量。它使用了分片和复制机制,将索引数据划分为多个分片,并在集群中的多个节点上进行复制,从而实现了数据的分布式存储和冗余备份。 对于搜索功能,Elasticsearch采用了倒排索引的概念,它通过建立字典来映射每个词项到包含该词项的文档,以实现快速的全文搜索。同时,它还支持各种查询类型和过滤器,可以根据不同的需求进行高级搜索和过滤。 此外,Elasticsearch还提供了灵活的数据分析功能,可以进行聚合、统计和数据可视化等操作。它内置了强大的聚合框架,可以对数据进行复杂的分组、求和、平均等操作,以便更好地理解和分析数据。 另外,Elasticsearch还支持实时索引和搜索,可以实时地从更新的数据中搜索和获取结果。它采用了近乎实时的索引策略,可以保证数据的低延迟和高吞吐量。 总结来说,Elasticsearch作为一款分布式搜索分析引擎,具有高可伸缩性、快速的搜索分析能力,可以帮助用户高效地处理大规模数据,并从中获取有用的信息和洞察。它广泛应用于各个领域,如企业搜索、日志分析、数据挖掘等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大家都说我身材好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值