- ElasticSearch-helper
- 适应场景
- 结构
- 使用方法
- 扩展
- 结语
使用ElasticSearch作为分析,检索的数据源进行开发已经有一段时间了,经历了大大小小的几个项目,从初次接触这个技术,惊叹于它巧妙的设计,同时也惊叹它恶心的访问api;在初学时我时常会望着前辈开发的绵绵不觉的链式调用无所适从,到处寻找需要调整的参数;之后在一个项目中我遇到了一个逆天的搜索框,条件密密麻麻达几十个之多,过滤,模糊,范围应有竟有(不讨论设计的合理性,也许存在即合理吧),于是那个搜索方法的代码行数被干到了1000+,于是我在想是不是可以设计这样一个框架,将es的查询语句用对象来描述,让查询条件的实体类自己来说明自己想要做什么样的查询,因此我开发了Elasticsearch-helper。
项目地址仓库地址:https://gitee.com/JohenTeng/elasticsearch-helper.git
使用示例地址:https://gitee.com/JohenTeng/elasticsearch-helper-sample.git
elasticsearch-helper主要是针对查询进行了封装,当前版本并没有对DDL以及增删改做过多的支持,因为增删改涉及到较多的专有api,比如批量,异步,回调等等;因此该框架适用于使用ElasticSearch作为数据源,且存在大量查询条件的系统。
结构
EsQueryEngine: 接受查询对象,生成es查询对象,该对象需要使用 @EsQueryIndex 描述对象,使用 org/pippi/elasticsearch/helper/core/beans/annotation/query/module 下的注解描述属性: @Match,@MultiMatch,@Term … … 等
RequestHook: 扩展接口,实现Request描述的扩展
ResponseHook: 扩展接口,自定义解读 es 的 SearchResponse
主方法中:
@EnableEsHelper // 启用EsHelper框架
@SpringBootApplication(scanbasePackages = "com.sun")
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
在 spring-boot配置中定义:
.properties 配置:
## 配置日志是否打印 elasticsearch的查询语句
es.helper.queryLogOut.enable = true
## 配置自定义处理类所在位置:
es.helper.ext.handle-packages = ***
.yml 配置:
es:
helper:
queryLogOut:
enable: true
ext:
handle-packages: com.***.***.handles1,com.***.***.handles2
查询对象:
@EsQueryIndex(index = "test", model = QueryModel.BOOL)
// 是否启用高亮
@HighLight(fields = {"title", "describe"})
public class DemoSearchParam {
// 范围查询
@Range(value = @base, tag = Range.LE_GE)
private RangeParam intensity;
@MultiMatch(value = @base,fields = {"title", "describe"})
private String title;
}
返回对象:
// 默认的查询结果处理结果类需要 继承 baseResp.baseHit
public class Content extends baseResp.baseHit {
private int intensity;
private String title;
}
被代理接口:
@EsHelperProxy
public interface TestQueryService {
baseResp queryRecordByIntensity(ContentSearchParam param)
}
调用:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SampleApplication.class)
public class TestQueryBeanServiceTest {
@Resource
private TestQueryService testQueryService;
@Test
public void testQueryService(){
ContentSearchParam param = new ContentSearchParam();
RangeParam rangeParam = new RangeParam();
rangeParam.setLeft(12);
rangeParam.setRight(15);
param.setIntensity(rangeParam);
param.setTitle("测试测试");
baseResp baseResp = testQueryService.queryRecordByIntensity(param);
System.out.println(SerializerUtils.parseObjToJson(baseResp));
}
}
扩展
=> 包:org.pippi.elasticsearch.helper.core.beans.annotation.query.mapping.extend下定义的类:
MoreLikeThisParam:@MoreLikeThis修饰的类属性需要定义为该类型;
PageParam:@PageAndOrder修饰的类属性需要定义为该类型;
RangeParam:@Range修饰的类属性需要定义为该类型;
=> 关于钩子方法:
包:org.pippi.elasticsearch.helper.core.hook
作用:我们无法定义所有的查询场景,因此需要使用钩子方法来自定义查询类以及结果处理方法
接口:
@FunctionalInterface RequestHook#handleRequest
@FunctionalInterface ResponseHook#handleResponse
我们可以通过让查询对象 继承 HookQuery抽象类,实现其中的set方法,如:
public class DemoParam extends HookQuery {
@Match(value = @base)
private String Field;
@Override
public void setRequestHook() {
super.requestHook = (h, p) -> h;
}
@Override
public void setResponseHook() {
super.responseHook = resp -> null;
}
}
或者 在代码中定义公共的钩子方法,如:
public interface MySearchHooks extends UserHooks {
RequestHook reqHook1 = (h, p) -> h;
ResponseHook respHook1 = resp -> null;
}
使用:
@EsHelperProxy
public interface TestQueryService {
// 查询在处理了 查询类中的注解定义之后会执行 RequestHook 钩子
// 得到Es返回原始对象后 会使用 结果处理钩子,返回钩子定义的对象
@UseRequestHook("reqHook1")
@UseResponseHook("respHook1")
baseResp queryRecordByIntensity(ContentSearchParam param);
}
=> 关于高亮:
高亮在同一个系统中定义应该是类似的;
我们可以在配置Bean中调用全局高亮配置类,定义不同的高亮配置
class AutoConfiguration {
void config {
// 定义
GlobalEsQueryConfig.configHighLight(DEFAULT_KEY ,() -> SearchSourceBuilder.highlight());
GlobalEsQueryConfig.configHighLight("html" ,() ->
SearchSourceBuilder.highlight().fragmentSize(10).numOfFragments(5)
);
}
}
可以使用 @HighLight(fields = {"title", "describe"}, highLightKey = "html")
中的 highLightKey 来定义使用的HightLight配置
结语
目前,我并没有把它打包放入中央仓库,因为考虑到Elasticsearch的High-level-rest-client在各种细分版本中都有一些变动,目前项目的client版本为:7.13.3; 理论上是支持 7.*的elasticserch-server;
关于聚合查询的支持,因为聚合的场景较为复杂,很难通过注解进行合适的描述,因此我们需要在钩子方法中定义查询的聚合行为。
希望这个轮子能为大家带来方便,欢迎多多指出问题和不足,谢谢各位客官。



