这是针对ES查询的一套封装。 因为时间有限仅仅能够支持一些简单查询,但能满足大部分开发需求。
同时也封装了对索引以及数据的CRUD、批量处理。
public static void main(String[] args) {
try {
ElasticSearchService service = new ElasticSearchService("es", "192.168.1.1", 9300);
ESQueryBuilderConstructor constructor = new ESQueryBuilderConstructor();
constructor.must(new ESQueryBuilders().term("gender", "f").range("age", 20, 50));
constructor.should(new ESQueryBuilders().term("gender", "f").range("age", 20, 50).fuzzy("age", 20));
constructor.mustNot(new ESQueryBuilders().term("gender", "m"));
constructor.setSize(15); //查询返回条数,最大 10000
constructor.setFrom(11); //分页查询条目起始位置, 默认0
constructor.setAsc("age"); //排序
List<Map<String, Object>> list = service.search("bank", "account", constructor);
Map<Object, Object> map = service.statSearch("bank", "account", constructor, "state");
} catch (Exception e) {
e.printStackTrace();
}
}
条件接口
import org.elasticsearch.index.query.QueryBuilder;
import java.util.List;
public interface ESCriterion {
public enum Operator {
TERM, TERMS, RANGE, FUZZY, QUERY_STRING, MISSING
}
public enum MatchMode {
START, END, ANYWHERE
}
public enum Projection {
MAX, MIN, AVG, LENGTH, SUM, COUNT
}
public List<QueryBuilder> listBuilders();
}
查询条件容器
import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import java.util.ArrayList;
import java.util.List;
public class ESQueryBuilderConstructor {
private int size = Integer.MAX_VALUE;
private int from = 0;
private String asc;
private String desc;
//查询条件容器
private List<ESCriterion> mustCriterions = new ArrayList<>();
private List<ESCriterion> shouldCriterions = new ArrayList<>();
private List<ESCriterion> mustNotCriterions = new ArrayList<>();
//构造builder
public QueryBuilder listBuilders() {
int count = mustCriterions.size() + shouldCriterions.size() + mustNotCriterions.size();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
QueryBuilder queryBuilder = null;
if (count >= 1) {
//must容器
if (!CollectionUtils.isEmpty(mustCriterions)) {
for (ESCriterion criterion : mustCriterions) {
for (QueryBuilder builder : criterion.listBuilders()) {
queryBuilder = boolQueryBuilder.must(builder);
}
}
}
//should容器
if (!CollectionUtils.isEmpty(shouldCriterions)) {
for (ESCriterion criterion : shouldCriterions) {
for (QueryBuilder builder : criterion.listBuilders()) {
queryBuilder = boolQueryBuilder.should(builder);
}
}
}
//must not 容器
if (!CollectionUtils.isEmpty(mustNotCriterions)) {
for (ESCriterion criterion : mustNotCriterions) {
for (QueryBuilder builder : criterion.listBuilders()) {
queryBuilder = boolQueryBuilder.mustNot(builder);
}
}
}
return queryBuilder;
} else {
return null;
}
}
/**
* 增加简单条件表达式
*/
public ESQueryBuilderConstructor must(ESCriterion criterion){
if(criterion!=null){
mustCriterions.add(criterion);
}
return this;
}
/**
* 增加简单条件表达式
*/
public ESQueryBuilderConstructor should(ESCriterion criterion){
if(criterion!=null){
shouldCriterions.add(criterion);
}
return this;
}
/**
* 增加简单条件表达式
*/
public ESQueryBuilderConstructor mustNot(ESCriterion criterion){
if(criterion!=null){
mustNotCriterions.add(criterion);
}
return this;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getAsc() {
return asc;
}
public void setAsc(String asc) {
this.asc = asc;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getFrom() {
return from;
}
public void setFrom(int from) {
this.from = from;
}
}
条件构造器
import org.elasticsearch.index.query.QueryBuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ESQueryBuilders implements ESCriterion{
private List<QueryBuilder> list = new ArrayList<>();
/**
* 功能描述:Term 查询
* @param field 字段名
* @param value 值
*/
public ESQueryBuilders term(String field, Object value) {
list.add(new ESSimpleExpression (field, value, Operator.TERM).toBuilder());
return this;
}
/**
* 功能描述:Terms 查询
* @param field 字段名
* @param values 集合值
*/
public ESQueryBuilders terms(String field, Collection<Object> values) {
list.add(new ESSimpleExpression (field, values).toBuilder());
return this;
}
/**
* 功能描述:fuzzy 查询
* @param field 字段名
* @param value 值
*/
public ESQueryBuilders fuzzy(String field, Object value) {
list.add(new ESSimpleExpression (field, value, Operator.FUZZY).toBuilder());
return this;
}
/**
* 功能描述:Range 查询
* @param from 起始值
* @param to 末尾值
*/
public ESQueryBuilders range(String field, Object from, Object to) {
list.add(new ESSimpleExpression (field, from, to).toBuilder());
return this;
}
/**
* 功能描述:Range 查询
* @param queryString 查询语句
*/
public ESQueryBuilders queryString(String queryString) {
list.add(new ESSimpleExpression (queryString, Operator.QUERY_STRING).toBuilder());
return this;
}
public List<QueryBuilder> listBuilders() {
return list;
}
}
条件表达式
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import java.util.Collection;
import static com.scistor.label.labelstore.elasticsearch.ESCriterion.Operator;
public class ESSimpleExpression {
private String fieldName; //属性名
private Object value; //对应值
private Collection<Object> values; //对应值
private ESCriterion.Operator operator; //计算符
private Object from;
private Object to;
protected ESSimpleExpression(String fieldName, Object value, Operator operator) {
this.fieldName = fieldName;
this.value = value;
this.operator = operator;
}
protected ESSimpleExpression(String value, Operator operator) {
this.value = value;
this.operator = operator;
}
protected ESSimpleExpression(String fieldName, Collection<Object> values) {
this.fieldName = fieldName;
this.values = values;
this.operator = Operator.TERMS;
}
protected ESSimpleExpression(String fieldName, Object from, Object to) {
this.fieldName = fieldName;
this.from = from;
this.to = to;
this.operator = Operator.RANGE;
}
public QueryBuilder toBuilder() {
QueryBuilder qb = null;
switch (operator) {
case TERM:
qb = QueryBuilders.termQuery(fieldName, value);
break;
case TERMS:
qb = QueryBuilders.termsQuery(fieldName, values);
break;
case RANGE:
qb = QueryBuilders.rangeQuery(fieldName).from(from).to(to).includeLower(true).includeUpper(true);
break;
case FUZZY:
qb = QueryBuilders.fuzzyQuery(fieldName, value);
break;
case QUERY_STRING:
qb = QueryBuilders.queryStringQuery(value.toString());
}
return qb;
}
}
ES检索封装
import com.scistor.label.common.exception.MessageException;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class ElasticSearchService {
private final static int MAX = 10000;
TransportClient client;
/**
* 功能描述:服务初始化
* @param clusterName 集群名称
* @param ip 地址
* @param port 端口
*/
public ElasticSearchService (String clusterName, String ip, int port) {
try {
Settings settings = Settings.builder()
.put("cluster.name", clusterName).build();
this.client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(ip), port));
} catch (UnknownHostException e) {
throw new MessageException("es init failed!", e);
}
}
/**
* 功能描述:新建索引
* @param indexName 索引名
*/
public void createIndex(String indexName) {
client.admin().indices().create(new CreateIndexRequest(indexName))
.actionGet();
}
/**
* 功能描述:新建索引
* @param index 索引名
* @param type 类型
*/
public void createIndex(String index, String type) {
client.prepareIndex(index, type).setSource().get();
}
/**
* 功能描述:删除索引
* @param index 索引名
*/
public void deleteIndex(String index) {
if (indexExist(index)) {
DeleteIndexResponse dResponse = client.admin().indices().prepareDelete(index)
.execute().actionGet();
if (!dResponse.isAcknowledged()) {
throw new MessageException("failed to delete index.");
}
} else {
throw new MessageException("index name not exists");
}
}
/**
* 功能描述:验证索引是否存在
* @param index 索引名
*/
public boolean indexExist(String index) {
IndicesExistsRequest inExistsRequest = new IndicesExistsRequest(index);
IndicesExistsResponse inExistsResponse = client.admin().indices()
.exists(inExistsRequest).actionGet();
return inExistsResponse.isExists();
}
/**
* 功能描述:插入数据
* @param index 索引名
* @param type 类型
* @param json 数据
*/
public void insertData(String index, String type, String json) {
IndexResponse response = client.prepareIndex(index, type)
.setSource(json)
.get();
}
/**
* 功能描述:插入数据
* @param index 索引名
* @param type 类型
* @param _id 数据id
* @param json 数据
*/
public void insertData(String index, String type, String _id, String json) {
IndexResponse response = client.prepareIndex(index, type).setId(_id)
.setSource(json)
.get();
}
/**
* 功能描述:更新数据
* @param index 索引名
* @param type 类型
* @param _id 数据id
* @param json 数据
*/
public void updateData(String index, String type, String _id, String json) throws Exception {
try {
UpdateRequest updateRequest = new UpdateRequest(index, type, _id)
.doc(json);
client.update(updateRequest).get();
} catch (Exception e) {
throw new MessageException("update data failed.", e);
}
}
/**
* 功能描述:删除数据
* @param index 索引名
* @param type 类型
* @param _id 数据id
*/
public void deleteData(String index, String type, String _id) {
DeleteResponse response = client.prepareDelete(index, type, _id)
.get();
}
/**
* 功能描述:批量插入数据
* @param index 索引名
* @param type 类型
* @param data (_id 主键, json 数据)
*/
public void bulkInsertData(String index, String type, Map<String, String> data) {
BulkRequestBuilder bulkRequest = client.prepareBulk();
data.forEach((param1, param2) -> {
bulkRequest.add(client.prepareIndex(index, type, param1)
.setSource(param2)
);
});
BulkResponse bulkResponse = bulkRequest.get();
}
/**
* 功能描述:批量插入数据
* @param index 索引名
* @param type 类型
* @param jsonList 批量数据
*/
public void bulkInsertData(String index, String type, List<String> jsonList) {
BulkRequestBuilder bulkRequest = client.prepareBulk();
jsonList.forEach(item -> {
bulkRequest.add(client.prepareIndex(index, type)
.setSource(item)
);
});
BulkResponse bulkResponse = bulkRequest.get();
}
/**
* 功能描述:查询
* @param index 索引名
* @param type 类型
* @param constructor 查询构造
*/
public List<Map<String, Object>> search(String index, String type, ESQueryBuilderConstructor constructor) {
List<Map<String, Object>> result = new ArrayList<>();
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);
//排序
if (StringUtils.isNotEmpty(constructor.getAsc()))
searchRequestBuilder.addSort(constructor.getAsc(), SortOrder.ASC);
if (StringUtils.isNotEmpty(constructor.getDesc()))
searchRequestBuilder.addSort(constructor.getDesc(), SortOrder.DESC);
//设置查询体
searchRequestBuilder.setQuery(constructor.listBuilders());
//返回条目数
int size = constructor.getSize();
if (size < 0) {
size = 0;
}
if (size > MAX) {
size = MAX;
}
//返回条目数
searchRequestBuilder.setSize(size);
searchRequestBuilder.setFrom(constructor.getFrom() < 0 ? 0 : constructor.getFrom());
SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
SearchHits hits = searchResponse.getHits();
SearchHit[] searchHists = hits.getHits();
for (SearchHit sh : searchHists) {
result.add(sh.getSource());
}
return result;
}
/**
* 功能描述:统计查询
* @param index 索引名
* @param type 类型
* @param constructor 查询构造
* @param groupBy 统计字段
*/
public Map<Object, Object> statSearch(String index, String type, ESQueryBuilderConstructor constructor, String groupBy) {
Map<Object, Object> map = new HashedMap();
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);
//排序
if (StringUtils.isNotEmpty(constructor.getAsc()))
searchRequestBuilder.addSort(constructor.getAsc(), SortOrder.ASC);
if (StringUtils.isNotEmpty(constructor.getDesc()))
searchRequestBuilder.addSort(constructor.getDesc(), SortOrder.DESC);
//设置查询体
if (null != constructor) {
searchRequestBuilder.setQuery(constructor.listBuilders());
} else {
searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
}
int size = constructor.getSize();
if (size < 0) {
size = 0;
}
if (size > MAX) {
size = MAX;
}
//返回条目数
searchRequestBuilder.setSize(size);
searchRequestBuilder.setFrom(constructor.getFrom() < 0 ? 0 : constructor.getFrom());
SearchResponse sr = searchRequestBuilder.addAggregation(
AggregationBuilders.terms("agg").field(groupBy)
).get();
Terms stateAgg = sr.getAggregations().get("agg");
Iterator<Terms.Bucket> iter = stateAgg.getBuckets().iterator();
while (iter.hasNext()) {
Terms.Bucket gradeBucket = iter.next();
map.put(gradeBucket.getKey(), gradeBucket.getDocCount());
}
return map;
}
/**
* 功能描述:统计查询
* @param index 索引名
* @param type 类型
* @param constructor 查询构造
* @param agg 自定义计算
*/
public Map<Object, Object> statSearch(String index, String type, ESQueryBuilderConstructor constructor, AggregationBuilder agg) {
if (agg == null) {
return null;
}
Map<Object, Object> map = new HashedMap();
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);
//排序
if (StringUtils.isNotEmpty(constructor.getAsc()))
searchRequestBuilder.addSort(constructor.getAsc(), SortOrder.ASC);
if (StringUtils.isNotEmpty(constructor.getDesc()))
searchRequestBuilder.addSort(constructor.getDesc(), SortOrder.DESC);
//设置查询体
if (null != constructor) {
searchRequestBuilder.setQuery(constructor.listBuilders());
} else {
searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
}
int size = constructor.getSize();
if (size < 0) {
size = 0;
}
if (size > MAX) {
size = MAX;
}
//返回条目数
searchRequestBuilder.setSize(size);
searchRequestBuilder.setFrom(constructor.getFrom() < 0 ? 0 : constructor.getFrom());
SearchResponse sr = searchRequestBuilder.addAggregation(
agg
).get();
Terms stateAgg = sr.getAggregations().get("agg");
Iterator<Terms.Bucket> iter = stateAgg.getBuckets().iterator();
while (iter.hasNext()) {
Terms.Bucket gradeBucket = iter.next();
map.put(gradeBucket.getKey(), gradeBucket.getDocCount());
}
return map;
}
/**
* 功能描述:关闭链接
*/
public void close() {
client.close();
}
}