Skip to content

07-Elasticsearch 分布式搜索引擎

对应原始资料:微服务框架课件/04-Elasticsearch0105-Elasticsearch0206-Elasticsearch03

一、Elasticsearch 是什么

  • 基于 Lucene 的分布式搜索和分析引擎。
  • 倒排索引:根据词条快速找到对应文档,搜索效率极高。
  • 全文检索、结构化检索、聚合分析。

应用场景

  • 商品/文章搜索。
  • 日志分析(ELK:ES + Logstash + Kibana)。
  • 数据可视化(聚合)。

二、核心概念对照

关系型 DBElasticsearch
DatabaseIndex(索引)
TableType(已弱化)
RowDocument(文档,JSON)
ColumnField(字段)
SchemaMapping
SQLDSL(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:日期。
  • booleangeo_pointgeo_shapeobjectnested

六、文档 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)。

练习建议

  1. 用 Docker 启动 ES + Kibana,在 Kibana 控制台手写 DSL。
  2. 创建一个 hotel 索引,导入测试数据。
  3. 写一个多条件组合查询(关键字 + 价格范围 + 城市)。
  4. 用 SpringBoot 实现一个酒店搜索接口(分页 + 高亮)。
  5. 用聚合统计"每个品牌有多少家酒店、平均价格"。