原生的Rest Level Client不好用,构建检索等很多重复操作。
对bboss-elasticsearch进行了部分增强:通过注解配合实体类进行自动构建索引和自动刷入文档,复杂的业务检索需要自己在xml中写Dsl。用法与mybatis-plus如出一辙。
依赖
org.elasticsearch elasticsearchcom.bbossgroups.plugins bboss-elasticsearch-spring-boot-starter5.9.5 slf4j-log4j12 org.slf4j org.projectlombok lombok1.18.6 provided
配置:
import com.rz.config.ElsConfig;
import org.frameworkset.elasticsearch.boot.ElasticSearchBoot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
@Order(value = 1)
public class StartElastic implements ApplicationRunner {
@Autowired
private ElsConfig config;
@Override
public void run(ApplicationArguments args) throws Exception {
Map properties = new HashMap();
properties.put("elasticsearch.rest.hostNames", config.getElsClusterNodes());
ElasticSearchBoot.boot(properties);
}
}
注解和枚举:
package com.rz.szwes.annotations;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface ESDsl {
String value();
String indexName();
String indexType() default "";
}
package com.rz.szwes.annotations;
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface ESMapping {
//映射类型
ESMappingType value();
//加权
int boost() default 1;
//分词标识analyzed、not_analyzed
String index() default "analyzed";
//分词器ik_max_word、standard
String analyzer() default "ik_max_word";
//String作为分组聚合字段的时候需要设置为true
boolean fildData() default false;
}
package com.rz.szwes.annotations;
public enum ESMappingType {
text("text"),
keyword("keyword"),
/
_byte("byte"),
_short("short"),
_integer("integer"),
_long("long"),
/
_doule("doule"),
_float("float"),
half_float("half_float"),
scaled_float("scaled_float"),
/
date("date"),
_boolean("boolean"),
range("range"),
nested("nested"),
geo_point("geo_point"),
geo_shape("geo_shape"),
binary("binary"),
ip("ip");
private String value;
ESMappingType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
工具类:对HashMap进行了增强
package com.rz.szwes.util; import java.util.HashMap; import java.util.function.Supplier; public class LambdaHashMapextends HashMap { public static LambdaHashMap builder() { return new LambdaHashMap<>(); } public LambdaHashMap put(K key, Supplier supplier) { super.put(key, supplier.get()); //流式 return this; } }
核心类两个:
package com.rz.szwes.core; import cn.hutool.core.util.ClassUtil; import com.alibaba.fastjson.JSON; import com.frameworkset.orm.annotation.ESId; import com.rz.szwes.annotations.ESDsl; import com.rz.szwes.annotations.ESMapping; import com.rz.szwes.util.LambdaHashMap; import org.springframework.util.StringUtils; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; public abstract class AbstractElasticbase{ { //初始化解析 ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取第一个类型参数的真实类型 Class clazz = (Class ) pt.getActualTypeArguments()[0]; parseMapping(clazz); } protected String indexName; protected String indexType; protected String xmlPath; protected String mapping; //将Class解析成映射JSonString private void parseMapping(Class clazz) { if (clazz.isAnnotationPresent(ESDsl.class)) { ESDsl esDsl = clazz.getAnnotation(ESDsl.class); this.xmlPath = esDsl.value(); this.indexName = esDsl.indexName(); //如果类型为空,则采用索引名作为其类型 this.indexType = StringUtils.isEmpty(esDsl.indexType()) ? esDsl.indexName() : esDsl.indexType(); } else { throw new RuntimeException(clazz.getName() + "缺失注解[@ESDsl]"); } //构建索引映射 LambdaHashMap
package com.rz.szwes.core; import lombok.extern.slf4j.Slf4j; import org.frameworkset.elasticsearch.boot.BBossESStarter; import org.frameworkset.elasticsearch.client.ClientInterface; import org.frameworkset.elasticsearch.client.ClientUtil; import org.springframework.beans.factory.annotation.Autowired; import java.util.*; @Slf4j public class ElasticbaseServiceextends AbstractElasticbase { @Autowired private BBossESStarter starter; protected String createIndexByXml(String xmlName) { ClientInterface restClient = starter.getConfigRestClient(xmlPath); boolean existIndice = restClient.existIndice(this.indexName); if (existIndice) { restClient.dropIndice(indexName); } return restClient.createIndiceMapping(indexName, xmlName); } protected String createIndex() { ClientInterface restClient = starter.getRestClient(); boolean existIndice = restClient.existIndice(this.indexName); if (existIndice) { restClient.dropIndice(indexName); } log.debug("创建索引:" + this.mapping); return restClient.executeHttp(indexName, this.mapping, ClientUtil.HTTP_PUT); } protected String delIndex() { return starter.getRestClient().dropIndice(this.indexName); } protected String adddocument(T t, Boolean refresh) { return starter.getRestClient().adddocument(indexName, indexType, t, "refresh=" + refresh); } protected String adddocuments(List ts, Boolean refresh) { return starter.getRestClient().adddocuments(indexName, indexType, ts, "refresh=" + refresh); } protected void adddocumentsOfPage(List ts, Boolean refresh) { this.delIndex(); this.createIndex(); int start = 0; int rows = 100; Integer size; do { List list = pageDate(start, rows); if (list.size() > 0) { //批量同步信息 starter.getRestClient().adddocuments(indexName, indexType, ts, "refresh=" + refresh); } size = list.size(); start += size; } while (size > 0); } protected List pageDate(int start, int rows) { return null; } protected String deldocument(String id, Boolean refresh) { return starter.getRestClient().deletedocument(indexName, indexType, id, "refresh=" + refresh); } protected String deldocuments(String[] ids, Boolean refresh) { return starter.getRestClient().deletedocumentsWithrefreshOption(indexName, indexType, "refresh=" + refresh, ids); } protected T getdocument(String id, Class clazz) { return starter.getRestClient().getdocument(indexName, indexType, id, clazz); } protected String updatedocument(String id, T t, Boolean refresh) { return starter.getRestClient().updatedocument(indexName, indexType, id, t, "refresh=" + refresh); } }
写复杂Dsl的xml:(如何写Dsl请参考bBoss-elasticsearch文档,用法类似mybatis标签)
框架集成完毕,以下是使用示例:
定义数据模型:
package com.rz.dto;
import com.frameworkset.orm.annotation.ESId;
import com.rz.szwes.annotations.ESDsl;
import com.rz.szwes.annotations.ESMapping;
import com.rz.szwes.annotations.ESMappingType;
import lombok.Data;
import java.util.List;
@ESDsl(value = "elasticsearch/zsInfo.xml", indexName = "zsInfo")
@Data
public class ElasticZsInfoDto {
@ESMapping(ESMappingType._byte)
private int least_hit;
private int is_must_zz;
private int zs_level;
private int cur_zs_ct;
private int least_score_yy;
private int least_score_yw;
private int area_id;
private String coll_name;
private String coll_code;
private long coll_pro_id;
private int is_must_wl;
private int cur_year;
private int is_two;
private long logo;
@ESId
private int id;
private String area;
private int college_id;
private String is_must_yy;
private int is_double;
private int least_score_zz;
private int least_score_wl;
private String grade;
private int is_nine;
private String pro_name;
private int least_score_sx;
private int relevanceSort;
private int pre_avg;
private String is_must_dl;
private String profession_code;
private int least_score_sw;
private String is_must_ls;
private int grade_zk;
private int least_score_wy;
private int is_must_hx;
private int profession_id;
private String is_grad;
private String is_must_yw;
private int is_must_sw;
private int least_score_ls;
private int least_score_dl;
private String zs_memo;
private String is_must_sx;
private String introduce;
private int is_must_wy;
private int grade_bk;
private String pre_name;
private int least_score_hx;
private String coll_domain;
private int pre_wch;
private List courses;
}
定义服务
package com.rz.service; import com.rz.dto.ElasticZsInfoDto; import com.rz.szwes.core.ElasticbaseService; public class ElasticZsInfoService extends ElasticbaseService{ }
完毕。
已经可以进行索引和文档的crud操作了,至于复杂的检索操作就需要在xml中定义了。这里只介绍了我增强的功能,大部分功能都在bBoss中定义好了,读者可以去看bBoss文档(笔者认为的他的唯一缺陷是不能通过实体配合注解实现自动索引,还要每次手动指定xml位置,手动写mapping是很痛苦的事情,特此进行了增强)。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持考高分网。如有错误或未考虑完全的地方,望不吝赐教。



