Elasticsearch(ES)是基于Lucene的分布式搜索引擎,核心能力是全文搜索和实时分析。本文从倒排索引讲起,覆盖ES的基本使用。
倒排索引原理
传统数据库用正排索引:给定文档ID -> 获取内容。倒排索引反过来:给定关键词 -> 获取包含该词的文档列表。
假设有两篇文档:
- Doc1: "Java并发编程指南"
- Doc2: "Java虚拟机调优"
倒排索引结构:
| Term | Posting List |
|---|---|
| java | [Doc1, Doc2] |
| 并发 | [Doc1] |
| 编程 | [Doc1] |
| 指南 | [Doc1] |
| 虚拟机 | [Doc2] |
| 调优 | [Doc2] |
搜索"Java调优"时,ES查找"java"和"调优"对应的文档列表,取交集/并集,再根据相关性打分排序。
分词器 (Analyzer)
分词是构建倒排索引的前提。Analyzer由三部分组成:
- Character Filter:预处理原始文本(如去除HTML标签)
- Tokenizer:将文本切分为词条(token)
- Token Filter:对词条做转换(如小写化、去停用词、同义词)
内置分词器:
standard:按Unicode分词,适合英文ik_max_word/ik_smart:中文分词插件IK,max_word做最细粒度切分,smart做智能切分
测试分词效果:
POST /_analyze
{
"analyzer": "ik_smart",
"text": "Elasticsearch是分布式搜索引擎"
}
Mapping定义
Mapping定义字段类型和索引方式,类似数据库的Schema:
PUT /blog_posts
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"content": {
"type": "text",
"analyzer": "ik_max_word"
},
"author": {
"type": "keyword"
},
"publish_date": {
"type": "date",
"format": "yyyy-MM-dd"
},
"tags": {
"type": "keyword"
},
"view_count": {
"type": "integer"
}
}
}
}
text类型会被分词,用于全文搜索keyword类型不分词,用于精确匹配、聚合、排序- 一个字段可以同时有text和keyword两种索引(
fields多字段特性)
基本CRUD
// 创建文档(指定ID)
PUT /blog_posts/_doc/1
{
"title": "Elasticsearch入门教程",
"content": "本文介绍ES的基本概念和使用方法",
"author": "zhangsan",
"publish_date": "2021-08-19",
"tags": ["elasticsearch", "搜索"],
"view_count": 0
}
// 创建文档(自动生成ID)
POST /blog_posts/_doc
{
"title": "第二篇文章",
"content": "...",
"author": "lisi"
}
// 获取文档
GET /blog_posts/_doc/1
// 更新文档(部分更新)
POST /blog_posts/_update/1
{
"doc": {
"view_count": 100
}
}
// 删除文档
DELETE /blog_posts/_doc/1
Bool查询
Bool查询是ES中最常用的复合查询,由四种子句组成:
POST /blog_posts/_search
{
"query": {
"bool": {
"must": [
{ "match": { "content": "分布式搜索" } }
],
"should": [
{ "match": { "title": "入门" } }
],
"filter": [
{ "term": { "author": "zhangsan" } },
{ "range": { "publish_date": { "gte": "2021-01-01" } } }
],
"must_not": [
{ "term": { "tags": "deprecated" } }
]
}
}
}
- must:必须匹配,参与评分
- should:可选匹配,匹配则加分
- filter:必须匹配,不参与评分(性能更好,会被缓存)
- must_not:必须不匹配
经验法则:需要相关性评分的条件放must/should,只做过滤的条件放filter。
聚合 (Aggregations)
聚合相当于SQL的GROUP BY + 聚合函数:
POST /blog_posts/_search
{
"size": 0,
"aggs": {
"by_author": {
"terms": {
"field": "author",
"size": 10
},
"aggs": {
"avg_views": {
"avg": { "field": "view_count" }
}
}
},
"monthly_posts": {
"date_histogram": {
"field": "publish_date",
"calendar_interval": "month"
}
}
}
}
terms聚合:按字段值分组date_histogram:按时间区间分组- 聚合可以嵌套,实现多维度分析
ES的核心优势在于:倒排索引提供极快的全文搜索,加上分布式架构支持海量数据,再配合聚合能力做实时分析——这是传统关系数据库难以兼顾的。