← 全部文章

ElasticSearch基础

Elasticsearch 是一个开源的分布式搜索和分析引擎,专为速度、扩展和 AI 应用而打造。作为一个检索平台,它可以实时存储结构化、非结构化和向量数据,提供快速的混合和向量搜索,支持可观测性与安全分析,并以高性能、高准确性和高相关性实现 AI 驱动的应用。

更新于 2026.05.07

本文目录 14 节
ElasticSearch基础封面

通常使用Docker来安装启动,挂载本地目录以配置插件、数据等。

本文档基于Elast Search 7.12.1版本, 在 ES 7.x 之后,官方去掉了 Type(类型/表)的概念,现在的结构更趋向于:一个索引库(Index)就是一个独立的数据集。

默认端口:

  • 9200:对外http请求的端口
  • 9300:内部节点间通信的端口,采用特殊TCP协议

如果与关系型数据库类比

概念ElasticSearch关系型数据库 (MySQL)说明
存储单元Index (索引库)Database (数据库)数据的归类集合
数据结构Mapping (映射)Schema (表结构)定义字段类型(实、数字、布尔等)
数据实体Document (文档)Row (行)一条具体的 JSON 数据
数据属性Field (字段)Column (列)文档中的一个键值对

插件

  • kibana:提供了可视化的页面,帮助我们管理ElasticSearch。默认端口5601
  • ik分词器:ElasticSearch默认的分词规则对中文不够友好,无法理解中文语义。ik分词器则为中文分词场景提供了良好支持。

IK分词器

GitHub - infinilabs/analysis-ik: 🚌 The IK Analysis plugin integrates Lucene IK analyzer into Elasticsearch and OpenSearch, support customized dictionary.

安装

IK分词器支持两种分词方式,一种是在线安装,一种是离线安装。

离线安装:es的plugin目录:/var/lib/docker/volumes/es-plugins/_data。将ik分词器解压后,文件夹命名为ik,连同文件夹复制进该目录。

分词模式

  • ik_max_word:最细粒度拆分、会尽可能把文本切分成多个词、适合搜索时提高召回率
  • ik_smart:智能分词、更倾向于语义完整、词数量较少、适合减少冗余、提高精准度

拓展词词典和停用词词典

在实际开发中,IK 分词器自带的词库往往跟不上互联网梗、行业术语或品牌名的更新。比如,“瑞幸咖啡”可能会被拆成“瑞”、“幸”、“咖啡”,这时候就需要拓展词典(Extention Dictionary)来让它保持“专业性”。

同时,有一些敏感词不能参与搜索,需要被过滤。比如国家元首、敏感话筒、违禁词等,这个需要停用词词典。

IK 分词器主要通过配置 IKAnalyzer.cfg.xml 文件来管理自定义词库。 同一个类型的词典可以定义多个,用;分开,

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
  <comment>IK Analyzer 扩展配置</comment>
  <!-- 1. 扩展字典:添加你自己定义的词 -->
  <entry key="ext_dict">my_extra.dic;other.dic</entry>

  <!-- 2. 扩展停止词字典:添加你想要过滤掉、不参与搜索的词 -->
  <entry key="ext_stopwords">my_stop.dic</entry>

  <!-- 3. 远程扩展字典:支持热更新,非常重要 -->
  <entry key="remote_ext_dict">location</entry>
  <!-- 4. 远程扩展停止词字典 -->
  <entry key="remote_ext_stopwords">location</entry>
</properties>

静态拓展

在.dic文件中定义词,以换行符分隔即可。使用 UTF-8 无 BOM 格式。

DIC 文件位置:自定义的 .dic 文件必须放在 IK 插件的 config 目录下,或者其子目录下(路径要对应)。

动态拓展

对于高频变动的业务(如电商上新、舆情监控),频繁重启 ES 显然不现实。这时可以使用 remote_ext_dict。

原理:IK 会每隔一分钟左右发送一个 HTTP HEAD 请求到你指定的 URL。

判断标准:如果 HTTP Header 中的 Last-Modified 或 ETag 发生了变化,IK 就会自动拉取最新的词典内容并重新加载,全程无需重启 ES。

对于远程拓展的词典,IK分词器基于Last-Modified和ETag感知更新。请求头中的这两个字段发生变化,IK分词器会自动更新词典。

索引库

索引库是 ES 存储数据的地方。但在底层,它不仅仅是一个文件夹,而是一个逻辑命名空间,指向一个或多个Shards。

索引库通常由Settings和Mappings两部分组成。

如果将其与关系型数据库对比,索引库类似于MySQL中的Database。

索引库的创建

通过DSL语句创建索引库。

PUT /索引库名称
{
  "mappings": {
    "properties": {
      "字段名":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "字段名2":{
        "type": "keyword",
        "index": "false"
      },
      "字段名3":{
        "properties": {
          "子字段": {
            "type": "keyword"
          }
        }
      },
      // ...略
    }
  }
}

简单示例:

PUT /blog
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_smart"
      }
    }
  }
}

索引库的修改

在ES中,索引库已有的Mappings禁止被修改。倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改Mappings。

尽管无法对现有的Mappings禁止修改,但可以对现有索引库进行字段的添加。语法大致如下:

PUT /索引库名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}

索引库的查询和删除

非常简单。

GET /blog
DELETE /blog

文档

文档的插入

如果在插入文档时少写了几个字段,ES 不会报错。 如果某个文档没有包含 Mapping(映射)中定义的字段,ES 在存储时只会保存你提供的那些字段。甚至你可以插入 Mapping 中从未定义过的新字段。ES 默认会开启“动态映射(Dynamic Mapping)”,自动推断新字段的类型并将其加入索引库。

文档操作的语法也非常简单,不再赘述。

文档的查询和删除

Restful语法不再赘述。

文档的修改

全量修改

简单的PUT请求,本质是先删掉旧的,再把新的加进去。(根据ID)

事实上,PUT操作既可以修改,也可以新增(ID不存在)。

PUT /索引库名/_doc/文档id
{...}

局部修改

POST /索引库名/_update/文档id
{
  "doc":{
    "字段名":"新的值",
    ...
  }
}

评论