07-Elasticsearch 分布式搜索引擎
对应原始资料:
微服务框架课件/04-Elasticsearch01、05-Elasticsearch02、06-Elasticsearch03
一、Elasticsearch 是什么
- 基于 Lucene 的分布式搜索和分析引擎。
- 倒排索引:根据词条快速找到对应文档,搜索效率极高。
- 全文检索、结构化检索、聚合分析。
应用场景
- 商品/文章搜索。
- 日志分析(ELK:ES + Logstash + Kibana)。
- 数据可视化(聚合)。
二、核心概念对照
| 关系型 DB | Elasticsearch |
|---|---|
| Database | Index(索引) |
| Table | Type(已弱化) |
| Row | Document(文档,JSON) |
| Column | Field(字段) |
| Schema | Mapping |
| SQL | DSL(JSON 查询) |
三、安装与启动
Docker
bash
docker run -d --name es -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
elasticsearch:7.12.1
docker run -d --name kibana --link es:elasticsearch -p 5601:5601 kibana:7.12.1- ES 端口:9200(HTTP)、9300(TCP)。
- Kibana:可视化界面
http://localhost:5601。
IK 分词器:中文分词必备,放入
plugins/ik。
四、IK 中文分词器
json
POST /_analyze
{ "analyzer": "ik_max_word", "text": "黑马程序员" }
// ik_smart:粗粒度 / ik_max_word:细粒度可自定义词典扩展词、停用词。
五、索引操作
json
// 创建索引 + mapping
PUT /hotel
{
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "ik_max_word" },
"price": { "type": "integer" },
"city": { "type": "keyword" },
"star": { "type": "byte" },
"location":{ "type": "geo_point" }
}
}
}
GET /hotel // 查看
DELETE /hotel // 删除字段类型
text:会分词,全文搜索。keyword:不分词,精确匹配(标签、城市)。integer/long/double:数值。date:日期。boolean、geo_point、geo_shape、object、nested。
六、文档 CRUD
json
POST /hotel/_doc/1
{ "name": "如家酒店", "price": 200, "city": "北京" }
GET /hotel/_doc/1
PUT /hotel/_doc/1
DELETE /hotel/_doc/1
POST /hotel/_bulk // 批量七、DSL 查询语法(重点)
json
GET /hotel/_search
{
"query": {
"match_all": {}
},
"from": 0, "size": 20,
"sort": [ { "price": "asc" } ],
"highlight": { "fields": { "name": {} } }
}1. 查询分类
| 类型 | 示例 |
|---|---|
| match_all | 全部 |
| match | 全文检索(先分词再查) |
| term | 精确匹配(不分词) |
| range | 范围 gte/lte |
| bool | 组合 must/should/must_not/filter |
| multi_match | 多字段检索 |
json
{
"query": {
"bool": {
"must": [ { "match": { "name": "如家" } } ],
"filter": [ { "range": { "price": { "lte": 500 } } },
{ "term": { "city": "北京" } } ]
}
}
}
must参与算分,filter不算分(更快,可缓存)。
2. 算分(相关度)
- TF-IDF / BM25。
function_score:自定义打分(如广告位加权)。
3. 聚合(Aggregation)
类似 SQL GROUP BY:
json
{
"size": 0,
"aggs": {
"by_brand": {
"terms": { "field": "brand", "size": 10 }
},
"avg_price": { "avg": { "field": "price" } }
}
}八、SpringBoot 整合
1. 依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>2. 实体
java
@Document(indexName = "hotel")
public class Hotel {
@Id private Long id;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String name;
@Field(type = FieldType.Keyword)
private String city;
@Field(type = FieldType.Integer)
private Integer price;
}3. Repository / ElasticsearchRestTemplate
java
public interface HotelRepository extends ElasticsearchRepository<Hotel, Long> {
}
@Autowired private ElasticsearchRestTemplate es;
NativeSearchQuery q = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("name", "如家"))
.withPageable(PageRequest.of(0, 10))
.build();
List<Hotel> list = es.queryForList(q, Hotel.class);实际项目也常用 RestHighLevelClient 直接发 DSL,更灵活。
九、集群与分片
- 分片 shard:索引水平拆分,分布在不同节点。
- 副本 replica:分片的拷贝,高可用。
- 节点角色:master、data、coordinating。
cerebro 工具可视化集群(资料中有 cerebro-0.9.4)。
练习建议
- 用 Docker 启动 ES + Kibana,在 Kibana 控制台手写 DSL。
- 创建一个 hotel 索引,导入测试数据。
- 写一个多条件组合查询(关键字 + 价格范围 + 城市)。
- 用 SpringBoot 实现一个酒店搜索接口(分页 + 高亮)。
- 用聚合统计"每个品牌有多少家酒店、平均价格"。