封装目的
- 简化elasticsearch API的使用方式,使用者可以不需要关心es的实现细节。
- 降低es的使用要求
- 提高开发者编码速度
首先看看查询和插入数据
ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);
ESBasicService service = context.getBean(ESBasicService.class);
QueryRule rule = new QueryRule();
rule.add(Restrictions.ge("age", 20)).add(Restrictions.like("name", "*王*"));
System.out.println(JSON.toJSONString(service.list(UserM.class, rule)));
service.createIndexAndMapping(UserM.class);
// 插入数据
List<UserM> users = new ArrayList<>();
UserM user = new UserM("张先生", 25);
users.add(user);
UserM user2 = new UserM("王大姐", 30);
users.add(user2);
UserM user3 = new UserM("王小二", 25);
users.add(user3);
int count = service.saveDatas(users);
System.out.println(count);
elasticsearch下载
elasticsearch下载地址
下载后解压,进入bin目录,运行elasticsearch.bat即可
pom.xml
- elasticsearch 使用6.6.0
- spring 使用5.2.6
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<elasticsearch.version>6.6.0</elasticsearch.version>
<spring.version>5.2.6.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
接口
public interface ESBasicService {
boolean indexExists(Class<?> clazz);
boolean deleteIndex(Class<?> clazz);
boolean createIndexAndMapping(Class<?> clazz);
<T> boolean saveData(T data);
<T> Integer saveDatas(Collection<T> datas);
<T> List<T> list(Class<T> clazz, QueryRule rule);
<T> T get(Class<T> clazz, Long id);
<T> void update(Long id, T data);
void delete(Long id, Class<?> clazz);
void delete(Class<?> clazz, QueryRule rule);
}
实现类
public class ESBasicServiceImpl implements ESBasicService {
private static final Logger log = LogManager.getLogger(ESBasicServiceImpl.class);
private TransportClient client;
@Override
public boolean indexExists(Class<?> clazz) {
return client.admin().indices().prepareExists(getIndexNameAndTypeName(clazz)).execute().actionGet().isExists();
}
@Override
public boolean deleteIndex(Class<?> clazz) {
client.admin().indices().prepareDelete(getIndexNameAndTypeName(clazz)).execute().actionGet();
return true;
}
@Override
public boolean createIndexAndMapping(Class<?> clazz) {
if (indexExists(clazz)) {
// 存在就删除重新创建
deleteIndex(clazz);
}
String index = getIndexNameAndTypeName(clazz);
CreateIndexResponse createIndexResponse = client.admin().indices().prepareCreate(index).execute().actionGet();
if (!createIndexResponse.isAcknowledged()) {
log.error("create index error:" + index);
return false;
}
PutMappingRequest putMapping = Requests.putMappingRequest(index).type(index).source(createMapping(clazz));
AcknowledgedResponse response = client.admin().indices().putMapping(putMapping).actionGet();
if (!response.isAcknowledged()) {
log.error("create mapping error, mname=" + index);
}
return true;
}
@Override
public <T> boolean saveData(T data) {
return saveDatas(Arrays.asList(data)) > 0;
}
@Override
public <T> Integer saveDatas(Collection<T> datas) {
if(null == datas || datas.isEmpty()) {
return 0;
}
List<XContentBuilder> contents = new ArrayList<XContentBuilder>();
for(T data:datas) {
contents.add(obj2XContent(data));
}
Class<?> clazz = datas.iterator().next().getClass();
String index = getIndexNameAndTypeName(clazz);
BulkRequestBuilder bulkRequest = client.prepareBulk();
for (XContentBuilder content:contents) {
IndexRequest request = client.prepareIndex(index, index).setSource(content).request();
bulkRequest.add(request);
}
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
if (bulkResponse.hasFailures()) {
for(BulkItemResponse item:bulkResponse.getItems()) {
log.info("insert error... msg="+item.getFailureMessage());
}
}
int count = bulkRequest.numberOfActions();
log.info("save success, count="+count);
return count;
}
@Override
public <T> List<T> list(Class<T> clazz, QueryRule rule) {
SearchResponse response = search(clazz, rule);
SearchHits hits = response.getHits();
SearchHit[] searchHists = hits.getHits();
List<T> list = new ArrayList<>();
for(SearchHit hit:searchHists) {
list.add(JSON.parseObject(JSON.toJSONString(hit.getSourceAsMap()), clazz));
}
return list;
}
@Override
public <T> T get(Class<T> clazz, Long id) {
QueryRule rule = new QueryRule();
rule.add(Restrictions.eq("id", id));
return list(clazz, rule).get(0);
}
@Override
public <T> void update(Long id, T data) {
String index = getIndexNameAndTypeName(data.getClass());
String esId = getESId(id, data.getClass());
UpdateRequest updateRequest = new UpdateRequest(index, index, esId);
updateRequest.doc(JSON.parseObject(JSON.toJSONString(data), Map.class));
client.update(updateRequest).actionGet();
}
@Override
public void delete(Long id, Class<?> clazz) {
delete(getESId(id, clazz), clazz);
}
@Override
public void delete(Class<?> clazz, QueryRule rule) {
List<String> esIds = getESIds(clazz, rule);
for(String id:esIds) {
delete(id, clazz);
}
}
private void delete(String id, Class<?> clazz) {
String index = getIndexNameAndTypeName(clazz);
DeleteRequest deleteRequest = new DeleteRequest(index, index, id);
client.delete(deleteRequest).actionGet();
}
private String getESId(Long dataId, Class<?> clazz) {
QueryRule rule = new QueryRule();
rule.add(Restrictions.eq("id", dataId));
SearchResponse response = search(clazz, rule);
SearchHits hits = response.getHits();
SearchHit[] searchHists = hits.getHits();
if(searchHists.length != 1) {
log.error("get data number is not one, id="+dataId);
return null;
}
return searchHists[0].getId();
}
private List<String> getESIds(Class<?> clazz, QueryRule rule) {
SearchResponse response = search(clazz, rule);
SearchHits hits = response.getHits();
SearchHit[] searchHists = hits.getHits();
List<String> ids = new ArrayList<>();
for(SearchHit hit:searchHists) {
ids.add(hit.getId());
}
return ids;
}
private SearchResponse search(Class<?> clazz, QueryRule rule) {
List<QueryCriterion> criterions = rule.getCriterions();
String index = getIndexNameAndTypeName(clazz);
SearchRequestBuilder srb = client.prepareSearch(index).setTypes(index);
srb.setExplain(true);
if(rule.getFirstResult() > -1 && rule.getMaxResults() > 0) {
srb.setFrom(rule.getFirstResult()).setSize(rule.getMaxResults());
}
BoolQueryBuilder builder = QueryBuilders.boolQuery();
for(QueryCriterion criterion:criterions) {
builder.filter(criterion.getBuilder());
}
srb.setPostFilter(builder);
List<String> sorts = rule.getOrderPropertyNames();
if(null != sorts && !sorts.isEmpty()) {
for(String s:sorts) {
srb.addSort(new FieldSortBuilder(s).order(rule.getSortMode()));
}
}
return srb.execute().actionGet();
}
private XContentBuilder createMapping(Class<?> clazz) {
XContentBuilder mapping = null;
try {
mapping = XContentFactory.jsonBuilder().startObject()
.startObject(getIndexNameAndTypeName(clazz)).startObject("properties");
Field[] fields = clazz.getDeclaredFields();
for(Field field:fields) {
if(field.getType().getTypeName().equals("java.lang.Long")){
mapping.startObject(field.getName()).field("type", "long").endObject();
} else if(field.getType().getTypeName().equals("java.lang.Integer") || field.getType().getTypeName().equals("int")){
mapping.startObject(field.getName()).field("type", "integer").endObject();
} else if(field.getType().getTypeName().equals("java.lang.Double")){
mapping.startObject(field.getName()).field("type", "double").endObject();
} else{
mapping.startObject(field.getName()).field("type", "keyword").endObject();
}
}
mapping.endObject().endObject().endObject();
} catch (IOException e) {
log.error("create mapping error:", e);
}
return mapping;
}
private <E> XContentBuilder obj2XContent(E data) {
XContentBuilder jsonBuild = null;
try {
// 使用XContentBuilder创建json数据
jsonBuild = XContentFactory.jsonBuilder();
jsonBuild.startObject();
Field[] fields = data.getClass().getDeclaredFields();
for(Field field:fields) {
field.setAccessible(true);
jsonBuild.field(field.getName(), field.get(data));
}
jsonBuild.endObject();
} catch (Exception e) {
log.error("obj2XContent error:", e);
}
return jsonBuild;
}
private String getIndexNameAndTypeName(Class<?> clazz) {
return clazz.getCanonicalName().toLowerCase();
}
public void setClient(TransportClient client) {
this.client = client;
}
}
查询构造器
public class QueryRule {
private int firstResult;
private int maxResults;
List<QueryCriterion> criterions = new ArrayList<>();
private List<String> orderPropertyNames;
private SortOrder sortMode = SortOrder.ASC;
public QueryRule add(QueryCriterion criterion) {
criterions.add(criterion);
return this;
}
public QueryRule clear(QueryCriterion criterion) {
criterions.clear();
firstResult = -1;
maxResults = 0;
return this;
}
public QueryRule addOrder(String ...name) {
orderPropertyNames.addAll(Arrays.asList(name));
return this;
}
public QueryRule orderDesc() {
this.sortMode = SortOrder.DESC;
return this;
}
public int getFirstResult() {
return firstResult;
}
public QueryRule setFirstResult(int firstResult) {
this.firstResult = firstResult;
return this;
}
public int getMaxResults() {
return maxResults;
}
public QueryRule setMaxResults(int maxResults) {
this.maxResults = maxResults;
return this;
}
public List<QueryCriterion> getCriterions() {
return criterions;
}
public List<String> getOrderPropertyNames() {
return orderPropertyNames;
}
public SortOrder getSortMode() {
return sortMode;
}
}
public class Restrictions {
public static QueryCriterion eq(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.eq);
}
public static QueryCriterion eq(String propertyName, Object ...value) {
return new ValuesExpression(propertyName, value);
}
public static QueryCriterion like(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.like);
}
public static QueryCriterion ne(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.ne);
}
public static QueryCriterion gt(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.gt);
}
public static QueryCriterion lt(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.lt);
}
public static QueryCriterion ge(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.ge);
}
public static QueryCriterion le(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.le);
}
public static QueryCriterion matchQuery(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, QueryCriterion.matchQuery);
}
public static QueryCriterion in(String propertyName, Collection<?> values) {
return new InExpression(propertyName, values);
}
public static QueryCriterion multipleFileds(String value, String ...propertyNames) {
return new MultipleFieldExpression(value, propertyNames);
}
}
public abstract class QueryCriterion {
public abstract QueryBuilder getBuilder();
public static final String eq = "=";
public static final String like = "like";
public static final String ne = "<>";
public static final String gt = ">";
public static final String lt = "<";
public static final String ge = ">=";
public static final String le = "<=";
public static final String matchQuery = "matchQuery";
}
public class SimpleExpression extends QueryCriterion {
private String propertyName;
private Object value;
private String op;
public SimpleExpression(String propertyName, Object value, String op) {
this.propertyName = propertyName;
this.value = value;
this.op = op;
}
public String getPropertyName() {
return propertyName;
}
public Object getValue() {
return value;
}
public String getOp() {
return op;
}
@Override
public QueryBuilder getBuilder() {
QueryBuilder qb = null;
switch (op) {
case eq:
qb = QueryBuilders.termQuery(propertyName, value);
break;
case like:
qb = QueryBuilders.wildcardQuery(propertyName, value.toString());
break;
case ne:
break;
case gt:
qb = QueryBuilders.rangeQuery(propertyName).gt(value);
break;
case lt:
qb = QueryBuilders.rangeQuery(propertyName).lt(value);
break;
case ge:
qb = QueryBuilders.rangeQuery(propertyName).gte(value);
break;
case le:
qb = QueryBuilders.rangeQuery(propertyName).lte(value);
break;
case matchQuery:
qb = QueryBuilders.matchQuery(propertyName, value);
break;
}
return qb;
}
}
public class InExpression extends QueryCriterion {
private String propertyName;
private Collection<?> values;
public InExpression(String propertyName, Collection<?> values) {
this.propertyName = propertyName;
this.values = values;
}
public String getPropertyName() {
return propertyName;
}
public Collection<?> getValues() {
return values;
}
@Override
public QueryBuilder getBuilder() {
return QueryBuilders.termsQuery(propertyName, values);
}
}
public class MultipleFieldExpression extends QueryCriterion {
private String []propertyName;
private String value;
public MultipleFieldExpression(String value, String ...propertyName) {
this.propertyName = propertyName;
this.value = value;
}
public String[] getPropertyName() {
return propertyName;
}
public String getValue() {
return value;
}
@Override
public QueryBuilder getBuilder() {
return QueryBuilders.multiMatchQuery(value, propertyName);
}
}
public class ValuesExpression extends QueryCriterion {
private String propertyName;
private Object []values;
public ValuesExpression(String propertyName, Object ...values) {
this.propertyName = propertyName;
this.values = values;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public void setValues(Object[] values) {
this.values = values;
}
@Override
public QueryBuilder getBuilder() {
return QueryBuilders.termsQuery(propertyName, values);
}
}
到此处暂时告一段落,只是做了简单的CRUD,各位大佬有更好的欢迎指导。
谢谢!!!