核心原理:全文检索 = 分词 → 构建倒排索引 → 查询分词 → 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());
}
六、常见坑 & 最佳实践
❌ 不要用
term查 text 字段:term 不分词,直接精确匹配词条,搜不到text 字段 analyzer=ik_max_word(索引),search_analyzer=ik_smart(查询)
过滤条件放
filter,不要放 must,减少打分,提升性能深分页不要用 from/size,大数据用
search_after同步:MySQL 数据 → ES,一般用 Canal / Binlog 同步,不要循环全量刷
实时性:ES 默认 1s refresh 间隔,不是写入立刻可搜
七、查询类型对比表
本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。
原文链接
欢迎访问