Easy-Es 是一款基于 ElasticSearch 官方 RestHighLevelClient 开发的增强型工具包,旨在通过简化操作、屏蔽底层细节,让开发者能够以类 MySQL 语法快速实现 ElasticSearch(以下简称 ES)的各类操作。其架构设计以 "简化开发" 为核心目标,融合了自动索引管理、智能查询转换、多框架集成等特性,同时保持了对 ES 原生功能的兼容性和扩展性。
一、整体架构概览
Easy-Es 的架构采用分层设计,从底层依赖到上层应用接口形成完整闭环,核心可分为基础设施层 、核心引擎层 、功能扩展层 、集成适配层 和应用接口层五大层级。各层级职责清晰、耦合度低,既保证了核心功能的稳定性,又为扩展场景提供了灵活支持。

📋 左侧:框架工作流程
- Scan Entity(扫描实体)
- 通过反射(reflection)和提取(extraction)机制
- 自动扫描项目中的实体类
- 分析实体类的字段和注解信息
- Analyse Index Name Column(分析索引名称列)
- 根据扫描到的实体信息
- 自动分析和确定ElasticSearch的索引名称
- 处理字段映射关系
- 执行CRUD操作
- insert(插入)
- update(更新)
- delete(删除)
- select(查询)等操作
- Injection Easy-Es Container(注入Easy-Es容器)
- 将处理后的操作注入到Easy-Es容器中
- 统一管理和执行ElasticSearch操作
🧩 右侧:框架模块组成
根据项目结构,Easy-Es框架包含以下核心模块:1. easy-es-boot-starter
- Spring Boot自动配置启动器
- 提供开箱即用的集成能力
- core(核心模块)
- 框架的核心功能实现
- 包含主要的业务逻辑
- extension(扩展模块)
- 提供框架的扩展功能
- 支持自定义扩展
- annotation(注解模块)
- 定义框架使用的各种注解
- 如索引映射、字段配置等注解
- common(通用模块)
- 提供通用的工具类和常量
- 框架内部共享的基础组件
从代码仓库结构来看,架构的物理载体通过模块化设计体现,主要包含以下核心模块:
easy-es-core
:核心引擎,负责查询转换、索引管理等核心逻辑;easy-es-annotation
:注解定义,提供实体与 ES 索引的映射配置;easy-es-common
:通用工具类,封装常量、异常、数据结构等;easy-es-boot-starter
/easy-es-spring
/easy-es-solon-plugin
:框架集成适配,支持 Spring Boot、Solon 等主流框架;easy-es-extension
:功能扩展,支持高亮、Geo 地理查询等高级特性;- 测试模块(
easy-es-spring-test
/easy-es-solon-test
):验证各层级功能的正确性。
二、核心层级设计
1. 基础设施层
基础设施层是架构的基石,负责对接 ES 底层客户端、管理配置、处理通用逻辑,为上层提供稳定的运行环境。
- 客户端管理 :基于 ES 官方 RestHighLevelClient 封装,通过自动配置(如
easy-es-boot-starter
中的EsAutoConfiguration
)初始化客户端,支持自定义连接参数(地址、端口、账号密码等),并维护客户端的生命周期。 - 配置中心 :提供全局配置(如索引前缀、默认分词器、索引托管模式等)和局部配置(如实体类注解配置),通过
GlobalConfig
统一管理,支持配置的动态生效。 - 通用工具 :
easy-es-common
模块封装了 JSON 解析(JsonUtils
)、类型转换、异常处理(EsException
)等工具类,避免上层模块重复开发。
2. 核心引擎层
核心引擎层是 Easy-Es 的 "大脑",负责将开发者的操作意图(如查询、新增、索引管理)转换为 ES 原生 API 调用,是框架 "简化开发" 特性的核心实现。
(1)查询转换引擎
查询转换是 Easy-Es 最核心的功能之一,其目标是将开发者编写的 Lambda 条件(如 eq(Document::getTitle, "Hi")
)转换为 ES 原生查询(如 TermQuery
),核心逻辑在 WrapperProcessor
类中实现。
-
条件解析 :开发者通过
EsWrappers.lambdaQuery()
构建查询条件,框架将条件封装为Param
对象(包含字段名、操作类型、值等信息),并通过树结构(TreeBuilder
)组织复杂条件(如嵌套and
/or
)。 -
递归构建查询 :
WrapperProcessor.initBoolQueryBuilder()
方法通过深度优先遍历条件树,递归解析Param
节点,根据操作类型(TERM
/MATCH
/RANGE
等)生成对应的 ES 查询对象(如TermQuery
/MatchQuery
),最终组合为BoolQuery
。 -
字段智能处理 :通过
EntityInfoHelper
解析实体类注解(如@IndexField
),自动处理字段映射(如自定义字段名@IndexField(value = "wu-la")
)、类型适配(如GEO_POINT
类型转换)、分词器选择(如analyzer = Analyzer.IK_SMART
),并智能判断是否需要拼接.keyword
后缀(针对 text 类型的精确查询)。
示例:当开发者调用 eq(Document::getTitle, "Hi")
时,框架会解析 title
字段的注解配置,若为 KEYWORD
类型,则直接生成 TermQuery(field="title", value="Hi")
;若为 TEXT
类型且需要精确查询,则自动转换为 TermQuery(field="title.keyword", value="Hi")
。
(2)索引管理引擎
Easy-Es 首创 "全自动索引托管" 模式,彻底解决索引创建、更新、数据迁移的痛点,核心逻辑包含索引元数据管理、版本控制和零停机迁移。
- 索引元数据解析 :通过
@IndexName
(指定索引名)、@Settings
(分片 / 副本配置)、@IndexField
(字段类型 / 分词器)等注解,解析实体类生成索引映射(Mapping)和设置(Settings)元数据,无需手动编写 JSON 映射文件。 - 托管模式:支持 "自动挡"(自动创建 / 更新索引)和 "手动挡"(开发者通过 API 手动操作),默认开启自动挡。通过比对实体类注解与 ES 中现有索引的元数据,自动判断是否需要更新索引,并生成差异 SQL(类 ALTER TABLE)。
- 零停机迁移 :当索引结构变更时,框架会创建新索引(如
easyes_document_v2
),通过 ES 别名(Alias)将读写请求无缝切换到新索引,同时异步迁移旧数据,整个过程无需停机,用户无感知。 - 分布式锁 :为避免多实例并发操作索引导致冲突,通过
ee-distribute-lock
索引实现分布式锁,确保索引操作的原子性(测试模块中特别强调运行索引相关用例时需注意锁机制)。
(3)CRUD 操作引擎
封装 ES 的增删改查操作,提供简洁的接口(如 documentMapper.insert()
/selectList()
),底层自动处理请求组装、响应解析和异常转换。
- 插入 / 更新 :通过
IndexRequest
/UpdateRequest
封装数据,根据@IndexId
注解判断是否自定义文档 ID(如关联 MySQL 主键),并支持批量操作(insertBatch()
)提升性能。 - 查询结果映射 :将 ES 返回的
SearchHit
转换为实体类对象,自动处理字段映射(如@IndexField(value = "wu-la")
对应 JSON 中的wu-la
字段)、高亮结果映射(@HighLight(mappingField = "highlightContent")
)、得分(@Score
)和距离(@Distance
)等特殊字段。 - 分页处理 :自动封装分页参数(
from
/size
),并支持通过PageHelper
风格的接口实现分页查询,简化分页逻辑。
3. 功能扩展层
扩展层基于核心引擎,提供 ES 特有的高级功能支持,满足复杂场景需求,主要包括:
- 高亮查询 :通过
@HighLight
注解配置高亮标签(preTag
/postTag
)、片段长度等,查询时自动添加高亮配置,并将结果映射到指定字段(如highlightContent
)。 - 地理查询 :支持
GEO_POINT
(经纬度)和GEO_SHAPE
(图形)类型,提供geoDistance()
/geoBoundingBox()
等方法,实现附近地点搜索、区域筛选等功能。 - 嵌套类型 :通过
@IndexField(fieldType = FieldType.NESTED)
注解定义嵌套对象(如List<User>
),支持嵌套查询(nestedQuery()
),解决 ES 嵌套文档的查询难题。 - 权重与评分 :支持通过
boost()
方法设置查询权重,通过@Score
注解获取文档得分,实现按相关性排序。 - 复合字段 :通过
@MultiIndexField
注解为同一字段配置多种分词器(如同时支持中文分词和拼音分词),满足多维度检索需求。
4. 集成适配层
适配层负责与主流开发框架集成,降低接入成本,目前支持:
-
Spring Boot :通过
easy-es-boot-starter
实现自动配置,扫描@EsMapper
接口并生成代理对象,开发者可直接注入DocumentMapper
调用方法,无需手动配置。 -
Spring :
easy-es-spring
模块提供 XML 配置支持(如XmlScannerAllTest
测试用例),兼容传统 Spring 项目。 -
Solon :
easy-es-solon-plugin
模块适配 Solon 框架,提供类似 Spring 的集成体验。
集成层的核心是通过 Spring 的 FactoryBean
或 Solon 的 BeanWrap
生成 Mapper 代理对象,将接口方法映射为核心引擎的具体操作,实现 "接口调用即 ES 操作"。
5. 应用接口层
应用接口层是开发者直接交互的入口,通过注解和接口定义简化使用流程:
- 实体注解 :开发者通过
@IndexName
/@IndexField
等注解定义实体与索引的映射关系(如Document
类),无需关注底层 Mapping 细节。 - Mapper 接口 :类似 MyBatis-Plus,定义
DocumentMapper extends BaseEsMapper<Document>
接口,继承insert()
/selectList()
等通用方法,也可通过注解自定义 SQL(类@Select
)。 - 条件构造器 :
EsWrappers.lambdaQuery()
提供链式 API(如eq()
/like()
/and()
),支持 Lambda 表达式避免 "魔法值",语法风格与 MyBatis-Plus 一致,降低学习成本。
三、核心流程示例
以 "查询标题为'Hi'且作者为'Guy'的文档" 为例,展示 Easy-Es 的核心流程:
-
开发者调用 :通过
documentMapper.selectList(EsWrappers.lambdaQuery(Document.class).eq(Document::getTitle, "Hi").eq(Document::getCreator, "Guy"))
发起查询。 -
条件封装 :框架将
eq
条件封装为Param
对象,构建条件树(根节点为AND
,子节点为两个TERM
操作)。 -
查询转换 :
WrapperProcessor
遍历条件树,解析Document
类注解,确认title
和creator
字段类型(如KEYWORD
),生成BoolQuery
(包含两个TermQuery
)。 -
请求执行:通过 RestHighLevelClient 发送查询请求,获取 ES 响应。
-
结果映射 :将响应中的
_source
字段映射为Document
对象,返回给开发者。
整个过程中,开发者无需编写任何 ES 原生 API 代码,仅通过类 MySQL 语法即可完成查询,代码量较直接使用 RestHighLevelClient 减少 70% 以上。
四、架构优势
- 低学习成本:复用 MyBatis-Plus 语法风格,开发者无需学习 ES 原生 API,会 MySQL 即可使用。
- 全自动索引管理:零配置实现索引创建、更新和数据迁移,解决 ES 索引运维痛点。
- 智能字段处理:自动判断字段类型、分词器和查询方式,减少小白用户的误用。
- 高扩展性:模块化设计支持自定义注解、查询类型和框架集成,满足个性化需求。
- 高性能:底层基于 RestHighLevelClient,保持 ES 原生性能,同时通过批量操作、异步迁移等优化提升效率。
五、总结
Easy-Es 架构以 "简化开发" 为核心,通过分层设计和模块化实现,将复杂的 ES 操作抽象为类 MySQL 语法,同时保留对高级功能的支持。其核心引擎层的查询转换和索引管理机制解决了 ES 开发的两大痛点,集成适配层确保了与主流框架的无缝对接,应用接口层降低了开发者的使用门槛。
无论是简单的 CRUD 还是复杂的高亮、地理查询,Easy-Es 都能通过简洁的 API 实现,大幅提升开发效率。未来,随着 ES 版本的迭代和用户需求的扩展,架构将继续优化扩展性,支持更多高级特性(如向量搜索、时序分析等),成为 ES 开发的首选工具包。