小易说IT 小易说IT

Elasticsearch 全文检索完整实战(中文优先,ES8.x)

核心原理:全文检索 = 分词 → 构建倒排索引 → 查询分词 → BM25 相关性打分;中文必须装 IK 分词器,默认 standard 只会单字拆分,搜中文很难用 环境:Docker 一键启动 ES + Kibana,Kibana Dev Tools 执行下面所有 DSL

一、第一步:启动 ES(Docker)

# ES 8.x 单节点,记得修改密码
docker run -d \
  --name es \
  -p 9200:9200 -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  -e "xpack.security.enabled=false" \
  elasticsearch:8.15.0

# Kibana
docker run -d \
  --name kibana \
  -p 5601:5601 \
  --link es:elasticsearch \
  kibana:8.15.0

访问:http://127.0.0.1:5601 → Dev Tools(控制台)

安装 IK 中文分词插件(重点!)

版本号必须和 ES 完全一致

docker exec -it es bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.15.0/elasticsearch-analysis-ik-8.15.0.zip
# 安装完重启es
docker restart es

IK 两种模式:

  • ik_max_word:建索引用,细粒度拆分,穷尽所有词

  • ik_smart:搜索用,粗粒度智能分词,符合人类语言

测试分词效果:

POST _analyze
{
  "analyzer": "ik_smart",
  "text": "SpringBoot整合Elasticsearch全文检索"
}

二、第二步:创建索引 + Mapping(全文检索最关键)

text:会分词,用于全文搜索;keyword:不分词,精确匹配、筛选、聚合;一般一个字段设置 text+keyword 双类型

创建索引 article,标题、内容使用 IK:

PUT /article
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "fields": {
          "keyword": {"type": "keyword"}
        }
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      },
      "author": {"type": "keyword"},
      "create_time": {"type": "date"}
    }
  }
}

三、第三步:写入测试文档

# 插入文档1
PUT /article/_doc/1
{
  "title": "SpringBoot整合Elasticsearch实现全文检索",
  "content": "Elasticsearch基于Lucene,适合海量文本的全文检索,支持中文分词、相关性排序",
  "author": "张三",
  "create_time": "2026-10-01"
}

# 插入文档2
PUT /article/_doc/2
{
  "title": "MySQL模糊查询和ES全文检索的区别",
  "content": "MySQL like %关键词% 不走索引,大数据量很慢;ES倒排索引毫秒级检索",
  "author": "李四",
  "create_time": "2026-10-02"
}

# 插入文档3
PUT /article/_doc/3
{
  "title": "Elasticsearch分词器IK使用教程",
  "content": "IK分词器解决ES中文单字分割问题,是国内做中文搜索标配",
  "author": "张三",
  "create_time": "2026-10-03"
}

四、第四步:全文检索 DSL(Query DSL,重点)

1. match 单字段全文检索(最常用)

分词匹配,命中任意分词就返回,_score 是相关性分数,默认按分数降序

GET /article/_search
{
  "query": {
    "match": {
      "title": "全文检索"
    }
  }
}

match 默认 or:分词后任意一个词命中即可;改成 and 需要全部词都出现

GET /article/_search
{
  "query": {
    "match": {
      "title": {
        "query": "ES 全文检索",
        "operator": "and"
      }
    }
  }
}

2. multi_match 多字段同时检索(搜索框常用)

同时搜标题 + 内容,还可以设置权重 ^2,标题命中权重更高

GET /article/_search
{
  "query": {
    "multi_match": {
      "query": "Elasticsearch 中文检索",
      "fields": ["title^2", "content"]
    }
  }
}

3. match_phrase 短语精确匹配(顺序不能乱,适合短语搜索)

必须连续、顺序一致,适合搜完整句子

GET /article/_search
{
  "query": {
    "match_phrase": {
      "content": "倒排索引毫秒级检索"
    }
  }
}

4. bool 组合查询(全文检索 + 过滤条件,业务最常用)

  • must:必须匹配(参与打分,全文检索放这里)

  • filter:过滤,不参与打分,缓存,性能更好(时间、状态、分类等)

  • should:可选匹配,增加相关性

  • must_not:不能匹配

GET /article/_search
{
  "query": {
    "bool": {
      "must": [
        {"multi_match": {"query": "全文检索", "fields": ["title^2","content"]}}
      ],
      "filter": [
        {"term": {"author": "张三"}},
        {"range": {"create_time": {"gte": "2026-09-01"}}}
      ]
    }
  }
}

5. 分页、高亮(前端搜索页标配)

GET /article/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "multi_match": {
      "query": "Elasticsearch",
      "fields": ["title^2", "content"]
    }
  },
  "highlight": {
    "fields": {
      "title": {},
      "content": {}
    }
  }
}

返回结果里 highlight 字段自带 <em>关键词</em>,前端直接渲染标红

五、Java SpringBoot 代码实现(你常用栈)

依赖(Maven)

<!-- ES8.x 官方客户端 -->
<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.15.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

配置类

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EsConfig {
    @Bean
    public ElasticsearchClient esClient(){
        RestClient restClient = RestClient.builder(HttpHost.create("http://127.0.0.1:9200")).build();
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        return new ElasticsearchClient(transport);
    }
}

全文检索方法(multi_match + 高亮)

public List<Article> search(String keyword) throws IOException {
    SearchResponse<Article> resp = esClient.search(s -> s
            .index("article")
            .query(q -> q.multiMatch(m -> m
                    .query(keyword)
                    .fields("title^2","content")
            ))
            .highlight(h->h.fields("title",f->f).fields("content",f->f)),
            Article.class
    );
    return resp.hits().hits().stream().map(hit->{
        Article art = hit.source();
        // 高亮回填
        if(hit.highlight().containsKey("title")){
            art.setTitle(hit.highlight().get("title").get(0));
        }
        if(hit.highlight().containsKey("content")){
            art.setContent(hit.highlight().get("content").get(0));
        }
        return art;
    }).collect(Collectors.toList());
}

六、常见坑 & 最佳实践

  1. ❌ 不要用 term 查 text 字段:term 不分词,直接精确匹配词条,搜不到

  2. text 字段 analyzer=ik_max_word(索引),search_analyzer=ik_smart(查询)

  3. 过滤条件放 filter,不要放 must,减少打分,提升性能

  4. 深分页不要用 from/size,大数据用 search_after

  5. 同步:MySQL 数据 → ES,一般用 Canal / Binlog 同步,不要循环全量刷

  6. 实时性:ES 默认 1s refresh 间隔,不是写入立刻可搜

七、查询类型对比表

查询

是否分词

用途

match

✅

普通全文检索

multi_match

✅

多字段搜索

match_phrase

✅

短语连续匹配

term

❌

精确匹配(keyword 字段)

range

❌

区间筛选(时间、数字)


本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://www.yijunzhao.cc/archives/elasticsearch-full-text-search-complete-practice-guide

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/