Jason
Published on 2025-05-24 / 27 Visits
0
0

Elastic Search 基础架构及语法

什么是Elastic Search?

它是一个开源的分布式搜索和分析引擎,用于处理海量数据。它支持近实时的全文搜索,结构化查询,数据分析等场景。它基于apache lucene构建,提供了简单易用的resful API

架构

                +-----------------+
                |   Client Apps   |
                +--------+--------+
                         |
         +---------------v------------------+
         |   Coordinating Nodes (无数据)     |
         +---------------+------------------+
                         |
         +---------------v------------------+
         |  Data Nodes (分片存储 + 计算)      |
         |  * Shard 1 Primary              |
         |  * Shard 1 Replica               |
         +---------------+------------------+
                         |
         +---------------v------------------+
         |  Dedicated Master Nodes (3节点)   |
         |  * 管理集群元数据                 |
         +---------------------------------+

应用场景

  • 日志分析

  • 监控系统/安全审计

  • 电商搜索

  • 实时数据分析

日志分析: 能够对海量日志进行索引和搜索,可以使用复杂的查询语句帮助运维人员快速查找和定位问题。

监控系统/安全审计: 高效储存和查询数据,支持按时间/指标类型等条件进行查询,从而快速定位性能问题/安全事件。

电商搜索: 通过强大的全文搜索能力,支持分词、模糊查询、同义词查询、多语言搜索等功能,解决传统数据库无法进行全文搜索的痛点,结合其他条件查询,提供更准确、更高效的搜索结果。同时支持高扩展性,可以轻松扩展到多个节点,处理海量数据,满足高并发的搜索请求。

实时数据分析: 能够实时处理和索引新数据,支持毫秒级的查询响应,确保用户能够获取最新的数据。

核心概念

术语

说明

索引(Index)

类似数据库中的“表”,存储具有相同结构的文档(如 user_index)。

文档(Document)

数据的基本单位,以 JSON 格式存储(如一条商品信息)。

分片(Shard)

索引被拆分为多个分片,分散到不同节点实现分布式存储和计算。

副本(Replica)

每个分片的拷贝,保障高可用和读取负载均衡。

节点(Node)

运行 Elasticsearch 的服务器实例,分为 Master、Data、Coordinating 节点。


索引相关

es中索引就是indices,相当于表或者说document

查看所有索引

GET /_cat/indices?v=true&pretty

查看特定索引:

GET /<index_name>?v=true&pretty

查看索引是否存在

HEAD /xdclass_shop

创建索引

PUT /<index_name>
{
  "settings": {
    "number_of_replicas": 0,
    "number_of_shards": 2
  }
}

修改索引设置

PUT /xdclass_shop/_settings
{
  "number_of_replicas": 1
}

文档相关

文档就是索引里的一条条记录了,相当于entry

通过文档id查询文档: GET /<index_name>/_doc/<doc_id>

新增doc(指定id)

PUT /<index_name>/_doc/<doc_id>
{
  "key":"value"
}

新增doc(不指定id)

POST /<index_name>/_doc/ #无id
{
  "key":"value"
}

批量导入

POST /<index_name>/_bulk
{ "index": { "_index": "<index_name>" } }
{"key":"value"}
# json不能换行,每一个json对象必须在新的一行。最后一个json对象结束后必须换行

修改doc

POST /<index_name>/_doc/<doc_id>
{
  "key":"value/new_value",
  "new_key":"new_value"
}
​
PUT /<index_name>/_doc/<doc_id>
{
  "key":"value/new_value",
  "new_key":"new_value"
}

搜索所有文档

GET /<indice_name>/_search

按条件搜索文档

具体看query DSL

GET /<index_name>/_search
{
  "query": {
    "<condition, like match>": {
      "key": "value"
    }
  }
}

删除文档

DELETE /<indice_name>/_doc/<doc_id>

数据类型

查看索引库字段类型

GET /<index_name>/_mapping

创建指定字段类型的索引库

// 没有index
PUT /<index_name>
{
  "mappings": {
    "properties": {
      "<key>": {
        "type":"<data_type:>"
      }
    }
  }
}

//修改现有index
PUT /<index_name>/_mapping
{
  "properties": {
    "<key>": {
      "type":"<data_type>"
    }
  }
}

倒排索引相关

倒排索引(Inverted Index)是一种数据库索引结构,它将文档中的内容映射到包含这些内容的文档。与传统的"正排索引"(文档→内容)相反,倒排索引是"内容→文档"的映射关系。它可以快速检索内容是否属于某个文档,所以需要分词器。

查看分词器分词效果

GET _analyze
{
  "analyzer":"<tokenizer_name>",
  "text":"<content>"
}

查看某个索引的分词器

POST /<index_name>/_analyze
{
  "field":"<field_name>",
  "text":"<content>"
}

Query DSL

Elasticsearch 的查询语法主要基于 JSON DSL(Domain-Specific Language),支持丰富的查询类型和聚合操作。

基础语法

所有查询都包裹在 query 或 aggs(聚合)中,基本格式如下:

GET /<index_name>/_search
{
  "_source":[<field_name>] # 可选参数,用于指定需要返回的field,
  "query": {           // 查询条件
    "<condition, like match>": {
      "key": "value"
    },
  "aggs": { ... },     // 聚合分析
  "sort": [ ... ],     // 排序
  "from": 0,           // 分页起始位置
  "size": 10           // 返回条数
  }
}

全文搜索查询

match 分词搜索

全文搜索,会讲查询条件分词并且与指定字段中的⽂本进⾏匹配。默认词与词是or的关系

{
  "query": {
    "match": {
      "field_name": "搜索词"  // 自动分词后匹配
    }
  }
}

//示例
{ "match": { "title": "苹果手机" } }

match_phrase - 短语匹配(需完整顺序)

match_phrase查询分析文本并根据分析的文本创建一个短语查询。这里的短语是指一个完整的token。match_phrase 会将检索关键词分词。match_phrase的分词结果必须在被检索字段的分词中都包含,而且顺序必须相同,而且默认必须都是连续的。

{
  "match_phrase": {
    "field_name": "完整短语"
  }
}

multi_match - 多字段匹配

{
  "multi_match": {
    "query": "关键词",
    "fields": ["title", "description"]  // 指定多个字段
  }
}

match_all

查询所有文档。此时查询条件为{}。 即不传key value

{
  "match_all": {
    "query": {},
  }
}

精确查询

term

用于精确匹配指定字段关键词,不进行分词

{
  "term": {
    "status": {        // 字段名
      "value": "published"  // 精确值
    }
  }
}

terms - 多值匹配

{
  "terms": {
    "tags": ["科技", "手机"]  // 匹配字段包含任意一个值
  }
}

range - 范围查询

{
  "range": {
    "price": {
      "gte": 1000,    // 大于等于
      "lte": 5000     // 小于等于
    }
  }
}

复合查询

bool - 组合逻辑查询

{
  "query": {
    "bool": {
      "must": [ ... ],      // AND 条件
      "must_not": [ ... ],  // NOT 条件
      "should": [ ... ],    // OR 条件
      "filter": [ ... ]     // 过滤(不计算评分)
    }
  }
}

// 示例:搜索价格在 1000-5000 元且包含“手机”的商品:
{
  "bool": {
    "must": [
      { "match": { "title": "手机" } }  //title中必须包含关键词手机
    ],
    "filter": [
      { "range": { "price": { "gte": 1000, "lte": 5000 } } } //价格是大于等于1000, 小于等于5000
    ]
  }
}
  • must:必须匹配,贡献算分;

  • must_not:必须不匹配,不贡献算分;

  • should:如果满足这些语句中任意语句,将增加_score,否则无任何影响,它们主要用于修正每个文档的相关性得分;

  • filter:必须匹配,但它不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

constant_score - 固定评分查询

Constant Score 查询是 Elasticsearch 中的一种查询方式,它可以将查询结果的评分设定为一个常量值,从而忽略相关性评分的计算。这种方式在需要执行过滤操作但不需要评分的场景中非常有用。

constant_score:本意(常量分数),可以将一个不变的常量应用到所有匹配的文档中。它常用于只需要执行一个filter而没有其他查询(例如评分查询)的情况下。term查询被放置在constant_score中,转换成不评分的filter。这种方式可以用来只有filter的bool查询中。

{
  "constant_score": {
    "filter": { ... },  // 过滤条件
    "boost": 1.2        // 固定评分值
  }
}

聚合查询(Aggregations)

指标聚合(Metrics)

{
  "aggs": {
    "avg_price": { "avg": { "field": "price" } },  // 计算均价
    "max_price": { "max": { "field": "price" } }   // 最高价
  }
}

桶聚合(Buckets)

{
  "aggs": {
    "group_by_brand": {
      "terms": { "field": "brand" }  // 按品牌分组
    }
  }
}

嵌套聚合

{
  "aggs": {
    "group_by_brand": {
      "terms": { "field": "brand" },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } }  // 每组计算均价
      }
    }
  }
}

排序与分页

排序

{
  "sort": [
    { "price": { "order": "desc" } },  // 按价格降序
    "_score"                           // 再按相关性评分排序
  ]
}

分页

{
  "from": 10,  // 跳过前10条
  "size": 5    // 返回5条
}

高亮显示

高亮显示(Highlighting)是一种功能,它用于在搜索结果中突出显示与用户查询匹配的文本片段。高亮显示可以帮助用户快速定位到搜索结果中与查询相关的部分,提升用户体验。例如,当用户搜索“苹果”时,高亮显示可以将文档中所有“苹果”这个词标红或加粗,让用户一眼就能看到匹配的内容。

{
  "query": { ... },
  "highlight": {
    "fields": {
      "title": {}  // 高亮title字段匹配内容
    }
  }
}

//示例
GET /your_index/_search
{
  "query": {
    "match": {
      "content": "苹果"
    }
  },
  "highlight": {
    "fields": {
      "content": {}
    }
  }
}
//返回结果
//content字段中匹配的词会被加<em>标签
{
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "your_index",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "content": "这是一个关于苹果的文档。"
        },
        "highlight": {
          "content": [
            "这是一个关于<em>苹果</em>的文档。"
          ]
        }
      }
    ]
  }
}

查询模板(Query Template)

使用 mustache 语法动态传参:

{
  "query": {
    "match": {
      "{{field}}": "{{value}}"  // 运行时替换变量
    }
  }
}

SQL 查询(需X-Pack插件)

GET /_sql?format=json
{
  "query": "SELECT * FROM products WHERE price > 1000 LIMIT 10"
}

性能优化技巧

  • 避免通配符查询:如 wildcard 性能较差。

  • 使用 filter 替代 must:过滤条件不计算评分,可缓存。

  • 限制返回字段:通过 _source: ["field1", "field2"] 减少数据传输。

完整示例

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "手机" } }
      ],
      "filter": [
        { "range": { "price": { "gte": 1000 } } }
      ]
    }
  },
  "aggs": {
    "brand_stats": {
      "terms": { "field": "brand" },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } }
      }
    }
  },
  "highlight": {
    "fields": { "title": {} }
  },
  "from": 0,
  "size": 10
}


Comment