import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang.ArrayUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder.Operator;
import org.elasticsearch.index.query.MatchQueryBuilder.Type;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
/**
*
* @ClassName:
* @Description:
* @author: zzy
* @date: 2017年9月7日 下午3:44:23
*/
public class CloudESUtils {
private static TransportClient client;
private static String ip="192.168.3.186";private static String port="9300";
private static Settings settings;
static{
try {
//ip = Utils.PT.getProps("es_ip");//ip或者域名地址
// port=Utils.PT.getProps("es_port");//端口
//String clusterName=Utils.PT.getProps("es_clusterName");//集群名称"elasticsearch_zxcity"
settings = Settings.settingsBuilder()
// .put("cluster.name", clusterName==null?"elasticsearch":clusterName) // 设置名称
.put("client.transport.ignore_cluster_name", true) // 忽略集群名字验证, 打开后集群名字不对也能连接上
.put("client.transport.sniff", true)
.build();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @return
* @throws Exception
*/
public static void createClient() throws Exception{
if(client==null){
client=TransportClient.builder().settings(settings).build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(ip), port==null?9300:Integer.parseInt(port)));
}
}
/**
*
*/
public static void close(){
if(client==null){
client.close();
}
}
/**
* 创建ES对应的mapping文件
* @param map {属性,类型(小写)}
* @param isHasLocation 是否需要地理位置字段,true会创建属性名为location的字段(值为lon子属性和lat子属性)
* @throws Exception
*/
public static void createMapping(String index,String indexType,Map<String,String> map,boolean isHasLocation) throws Exception{
IndicesExistsResponse indexResponse=client.admin().indices().prepareExists(index).get();
if(!indexResponse.isExists()){
CreateIndexResponse indexresponse = client.admin().indices()
//这个索引库的名称还必须不包含大写字母
.prepareCreate(index).execute().actionGet();
//System.out.println(indexresponse.isAcknowledged());
}
PutMappingRequestBuilder builder = client.admin().indices().preparePutMapping(index);
Set<Entry<String, String>> sets= map.entrySet();
XContentBuilder source = XContentFactory.jsonBuilder()
.startObject().startObject(indexType).startObject("properties");
for(Entry<String, String> entry : sets){
if(entry.getValue().equalsIgnoreCase("array")){
source.startArray(entry.getKey()).endArray();
}else{
source.startObject(entry.getKey()).field("type",entry.getValue().toLowerCase()).endObject();
}
}
if(isHasLocation){
source.startObject("location").field("type", "geo_point").field("geohash_prefix", true).endObject();
}
source.endObject().endObject().endObject();
builder.setType(indexType).setSource(source);
PutMappingResponse response = builder.execute().actionGet();
// System.out.println(response.isAcknowledged());
}
/**
* 创建ES对应的mapping文件
* @param map {属性,类型(小写)}
* @param isHasLocation 是否需要地理位置字段,true会创建属性名为location的字段(值为lon子属性和lat子属性)
* @throws Exception
*/
public static void createMapping(String index,String indexType,String[] filedNames,boolean isHasLocation) throws Exception{
IndicesExistsResponse indexResponse=client.admin().indices().prepareExists(index).get();
if(!indexResponse.isExists()){
CreateIndexResponse indexresponse = client.admin().indices()
//这个索引库的名称还必须不包含大写字母
.prepareCreate(index).execute().actionGet();
//System.out.println(indexresponse.isAcknowledged());
}
PutMappingRequestBuilder builder = client.admin().indices().preparePutMapping(index);
XContentBuilder source = XContentFactory.jsonBuilder()
.startObject().startObject(indexType).startObject("properties");
for(String entry : filedNames){
source.startObject(entry).field("type","string").endObject();
}
if(isHasLocation){
source.startObject("location").field("type", "geo_point").field("geohash_prefix", true).endObject();
}
source.endObject().endObject().endObject();
builder.setType(indexType).setSource(source);
PutMappingResponse response = builder.execute().actionGet();
// System.out.println(response.isAcknowledged());
}
/**
* 创建ES对应的mapping文件,待测试是否通过
* @param index
* @param indexType
* @param mappingJson
* @throws Exception
*/
public static void createMapping(String index,String indexType,String mappingJson) throws Exception{
IndicesExistsResponse indexResponse=client.admin().indices().prepareExists(index).get();
if(!indexResponse.isExists()){
CreateIndexResponse indexresponse = client.admin().indices()
//这个索引库的名称还必须不包含大写字母
.prepareCreate(index).execute().actionGet();
//System.out.println(indexresponse.isAcknowledged());
}
PutMappingRequestBuilder builder = client.admin().indices().preparePutMapping(index);
XContentBuilder source = XContentFactory.jsonBuilder()
.startObject().startObject(indexType).startObject("properties").startObject(mappingJson).endObject().endObject().endObject();
builder.setType(indexType).setSource(source);
PutMappingResponse response = builder.execute().actionGet();
// System.out.println(response.isAcknowledged());
}
/**
* 添加单条数据到ES中
* @param index
* @param indexType
* @param obj
* @throws Exception
*/
public static void create(String index,String indexType,String objJson,String id) throws Exception {
//创建索引库 需要注意的是.setRefresh(true)这里一定要设置,否则第一次建立索引查找不到数据
IndexRequestBuilder requestBuilder = client.prepareIndex(index, indexType);
Map<String,Object> map=getMapping(index, indexType);
if(null==map || map.isEmpty()){
requestBuilder.setRefresh(true);
}
IndexResponse response = requestBuilder.setId(id).setSource(objJson).get();
//System.out.println(response.isCreated());//true
}
/**
*
* @param index
* @param indexType
* @param objJson{属性名:值} 键值对json字符串
* @param id
* @throws Exception
*/
public static void update(String index,String indexType,String objJson,String id)throws Exception{
JSONObject obj=JSONObject.parseObject(objJson);
Set<Entry<String, Object>> set=obj.entrySet();
XContentBuilder source=XContentFactory.jsonBuilder().startObject();
for(Entry<String, Object> entry : set){
source.field(entry.getKey(),entry.getValue());
}
source.endObject();
UpdateResponse response = client.update(new UpdateRequest(index, indexType, id)
.doc(source)).get();
//System.out.println(response.isCreated());//false
}
/**
* 批量插入
* @param index
* @param indexType
* @param list
* @throws Exception
*/
public static void batchCreat(String index,String indexType,String listObjJson,String idKey)throws Exception{
//创建索引库 需要注意的是.setRefresh(true)这里一定要设置,否则第一次建立索引查找不到数据
IndexRequestBuilder requestBuilder = client.prepareIndex(index, indexType).setRefresh(true);
JSONArray list=JSONObject.parseArray(listObjJson);
for(int i=0;i<list.size();i++){
JSONObject obj=list.getJSONObject(i);
String id=obj.getString(idKey);
requestBuilder.setId(id).setSource(obj).get();
}
}
/**
* 删除index和下面所有的数据
* @param index
*/
public static void deleteIndex(String index){
IndicesExistsResponse indexResponse=client.admin().indices().prepareExists(index).get();
if(indexResponse.isExists()){
DeleteIndexResponse deleteIndexResponse = client.admin().indices()
.prepareDelete(index)
.execute().actionGet();
//System.out.println( deleteIndexResponse.isAcknowledged());
}
}
/**
* 删除index和type下面指定id的数据
* @param index
* @param indexType
* @param id
* @throws Exception
*/
public static boolean deleteById(String index,String indexType,String id) throws Exception{
DeleteResponse deleteResponse= client.delete(new DeleteRequest(index, indexType, id)).get();
return deleteResponse.isFound();
}
/**
* 获取index和type下面所有属性
* @param index
* @param indexType
* @throws Exception
*/
public static Map<String,Object> getMapping(String index,String indexType) throws Exception{
IndexMetaData indexMetaData=client.admin().cluster().prepareState().execute()
.actionGet().getState().getMetaData().getIndices().get(index);
if(indexMetaData==null){
return null;
}
ImmutableOpenMap<String, MappingMetaData> mappings=indexMetaData.getMappings();
if(null!=mappings && !mappings.isEmpty() && null!=mappings.get(indexType)){
return mappings.get(indexType).getSourceAsMap();
}
return null;
}
/**
* 根据id查询对象
* @param index
* @param indexType
* @param id
* @return
*/
public static Map<String,Object> get(String index,String indexType,String id){
GetResponse response = client.prepareGet(index, indexType, id)
.setOperationThreaded(false) // 线程安全
.get();
return response==null?null:response.getSource();
}
/**
* 新的geo查询方法,查询条件对象化
* @param index
* @param indexType
* @param condition
* @param from
* @param size
* @return
*/
public static Map<String,Object> geoSearch(String index,String indexType,ESCondition condition,int from,int size){
GeoDistanceQueryBuilder precision=null;
if(null!=condition && (condition.getLat()!=null && condition.getLat()>0) && (null!=condition.getLon() && condition.getLon()>0)){
// precision = QueryBuilders.geoHashCellQuery("location",
// new GeoPoint(lat, lon))
// .neighbors(true).precision(3);
//改为中心距离搜索,距离范围5500千米(中国最大跨度)
precision = QueryBuilders.geoDistanceQuery("location")
.point(condition.getLat(), condition.getLon()) // 中心点
.distance(5500, DistanceUnit.KILOMETERS);
}
SearchRequestBuilder searchRequestBuilder = client
.prepareSearch(index).setTypes(indexType);
QueryBuilder query=null;
if(null!=condition && null!=condition.getParams()){
query=getQueryWhere(condition.getParams());
}
if(query==null){
query=QueryBuilders.matchAllQuery();
}
if(null!=condition && null!=condition.getNotShowField() && condition.getNotShowField().length>0){
searchRequestBuilder.setFetchSource(null, condition.getNotShowField());
}
searchRequestBuilder.setQuery(query);
if(null!=precision){
searchRequestBuilder.setPostFilter(precision);
}
if(size>0){
searchRequestBuilder.setFrom(from).setSize(size);
}
if(null!=condition && null!=condition.getSorts()){
for(ESSortVo sortentry: condition.getSorts()){
searchRequestBuilder.addSort(sortentry.getSortName(),"ASC".equalsIgnoreCase(sortentry.getOrder())? SortOrder.ASC:SortOrder.DESC);
}
}
if(null!=precision){
GeoDistanceSortBuilder sort = new GeoDistanceSortBuilder("location");
sort.unit(DistanceUnit.METERS);//距离单位公里
sort.order(SortOrder.ASC);
sort.point(condition.getLat(), condition.getLon());//注意纬度在前,经度在后
searchRequestBuilder.addSort(sort);
}
SearchResponse searchresponse=searchRequestBuilder.setExplain(true).execute().actionGet();
Map<String,Object> resultMap=new HashMap<String,Object>();
List<Map<String,Object>> resultList=new ArrayList<Map<String,Object>>();
// System.out.println(JSONObject.toJSONString(searchresponse));
if(null!=searchresponse && null!=searchresponse.getHits()){
for (SearchHit hit : searchresponse.getHits()) {
Map<String,Object> map=hit.getSource();
// 获取距离值,并保留两位小数点
BigDecimal geoDis =(null!=precision && null!=hit.getSortValues() && hit.getSortValues().length>0 )?new BigDecimal((Double) hit.getSortValues()[hit.getSortValues().length-1]):new BigDecimal(0);
map.put("distance", geoDis.setScale(0,BigDecimal.ROUND_HALF_DOWN));
resultList.add(map);
}
resultMap.put("total", searchresponse.getHits().getTotalHits());
resultMap.put("list", resultList);
}
return resultMap;
}
/**
* 新的普通查询方法,查询条件对象化
* @param index
* @param indexType
* @param condition
* @param from
* @param size
* @return
*/
public static Map<String,Object> search(String index,String indexType,ESCondition condition,int from,int size){
SearchRequestBuilder searchRequestBuilder = client
.prepareSearch(index).setTypes(indexType);
QueryBuilder query=null;
if(null!=condition && null!=condition.getParams()){
query=getQueryWhere(condition.getParams());
}
if(query==null){
query=QueryBuilders.matchAllQuery();
}
if(null!=condition && null!=condition.getNotShowField() && condition.getNotShowField().length>0){
searchRequestBuilder.setFetchSource(null, condition.getNotShowField());
}
searchRequestBuilder.setQuery(query);
if(size>0){
searchRequestBuilder.setFrom(from).setSize(size);
}
if(null!=condition && null!=condition.getSorts()){
for(ESSortVo sortentry: condition.getSorts()){
searchRequestBuilder.addSort(sortentry.getSortName(),"ASC".equalsIgnoreCase(sortentry.getOrder())? SortOrder.ASC:SortOrder.DESC);
}
}
SearchResponse searchresponse=searchRequestBuilder.setExplain(true).execute().actionGet();
Map<String,Object> resultMap=new HashMap<String,Object>();
List<Map<String,Object>> resultList=new ArrayList<Map<String,Object>>();
// System.out.println(JSONObject.toJSONString(searchresponse));
if(null!=searchresponse && null!=searchresponse.getHits()){
for (SearchHit hit : searchresponse.getHits()) {
Map<String,Object> map=hit.getSource();
resultList.add(map);
}
resultMap.put("total", searchresponse.getHits().getTotalHits());
resultMap.put("list", resultList);
}
return resultMap;
}
/**
* 更加查询参数获取查询条件
* @param params
* @return
*/
private static QueryBuilder getQueryWhere(List<ESWhereVo> params){
if(null!=params && !params.isEmpty()){
BoolQueryBuilder filter=QueryBuilders.boolQuery();
for(ESWhereVo where : params){
if(null!=where.getOrWhere() && null!=where.getOrWhere()){
BoolQueryBuilder or=new BoolQueryBuilder();
or.should(getBoolQueryBuilder(where));
or.should(getBoolQueryBuilder(where.getOrWhere()));
filter.must(or);
}else{
filter.must(getBoolQueryBuilder(where));
}
}
return filter;
}
return null;
}
/**
* 根据查询参数对象获取查询条件对象
* @param where
* @return
*/
private static QueryBuilder getBoolQueryBuilder(ESWhereVo where){
if(!isNaN(where.getParamKey()) && null==where.getParamKeys()){
if("eq".equalsIgnoreCase(where.getOperater()) && where.getValue() instanceof List){
return QueryBuilders.termsQuery(where.getParamKey(), (List<Object>)where.getValue());
}else if("eq".equalsIgnoreCase(where.getOperater()) && !(where.getValue() instanceof List)){
return QueryBuilders.termsQuery(where.getParamKey(),where.getValue());
}else if("neq".equalsIgnoreCase(where.getOperater()) && !(where.getValue() instanceof List)){
return QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery(where.getParamKey(),where.getValue()));
}else if("neq".equalsIgnoreCase(where.getOperater()) && where.getValue() instanceof List){
return QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(where.getParamKey(), (List<Object>)where.getValue()));
}else if("like".equalsIgnoreCase(where.getOperater()) && !(where.getValue() instanceof List)){
return QueryBuilders.matchPhrasePrefixQuery(where.getParamKey(), where.getValue());
}
}else if(isNaN(where.getParamKey()) && null!=where.getParamKeys()){ //多key相同值模糊查询目前只做一种情况
//优化搜索词模糊匹配,搜索短词完全匹配,(英文连词不支持,如eeeee,中文连词支持),比下面注释的精确
BoolQueryBuilder moreLike=new BoolQueryBuilder();
for(String key :where.getParamKeys()){
//moreLike.should(QueryBuilders.matchPhraseQuery(isSameLikeKeys[0], isSameLikeVal));
//功能同上,可以支持英文单词匹配,同样字母连词不支持
moreLike.should(QueryBuilders.matchPhrasePrefixQuery(key, "*"+where.getValue()+"*"));
}
return moreLike;
}
return null;
}
private static boolean isNaN(String str){
if(null==str || "".equals(str.trim())){
return true;
}
return false;
}
}
import java.io.Serializable;
import java.util.List;
/**
* ES查询和排序对象封装类
* @author zye
*
*/
public class ESCondition implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* geo维度
*/
private Double lat;
/**
* geo经度
*/
private Double lon;
/**
* 不需要显示的字段
*/
private String[] notShowField;
/**
* 查询条件
*/
private List<ESWhereVo> params;
/**
* 排序
*/
private List<ESSortVo> sorts;
public List<ESWhereVo> getParams() {
return params;
}
public void setParams(List<ESWhereVo> params) {
this.params = params;
}
public List<ESSortVo> getSorts() {
return sorts;
}
public void setSorts(List<ESSortVo> sorts) {
this.sorts = sorts;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
public String[] getNotShowField() {
return notShowField;
}
public void setNotShowField(String[] notShowField) {
this.notShowField = notShowField;
}
}
import java.io.Serializable;
/**
* 查询参数封装类
* @author zye
*
*/
public class ESWhereVo implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 参数名
*/
private String paramKey;
/**
* 多个参数名,与paramKey只能选择一个
*/
private String[] paramKeys;
/**
* 值
*/
private Object value;
/**
* 是or还是and 目前都是and
*/
private String orAnd;
/**
* 查询类型,eq 和neq和 like
*/
private String operater;
/**
* 并列的或者查询条件(只考虑一次嵌套)
*/
private ESWhereVo orWhere;
public ESWhereVo(){
}
public ESWhereVo(String paramKey, String[] paramKeys, Object value,
String orAnd, String operater) {
super();
this.paramKey = paramKey;
this.paramKeys = paramKeys;
this.value = value;
this.orAnd = orAnd;
this.operater = operater;
}
public ESWhereVo(String paramKey, String[] paramKeys, Object value,
String orAnd, String operater, ESWhereVo orWhere) {
super();
this.paramKey = paramKey;
this.paramKeys = paramKeys;
this.value = value;
this.orAnd = orAnd;
this.operater = operater;
this.orWhere = orWhere;
}
public String getParamKey() {
return paramKey;
}
public void setParamKey(String paramKey) {
this.paramKey = paramKey;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String[] getParamKeys() {
return paramKeys;
}
public void setParamKeys(String[] paramKeys) {
this.paramKeys = paramKeys;
}
public String getOperater() {
return null==operater||"".equals(operater.trim())?"eq":operater;
}
public void setOperater(String operater) {
this.operater = operater;
}
public ESWhereVo getOrWhere() {
return orWhere;
}
public void setOrWhere(ESWhereVo orWhere) {
this.orWhere = orWhere;
}
public String getOrAnd() {
return null==orAnd||"".equals(orAnd.trim())?"and":orAnd;
}
public void setOrAnd(String orAnd) {
this.orAnd = orAnd;
}
}
import java.io.Serializable;
/**
* ES排序
* @author zye
*
*/
public class ESSortVo implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 排序字段
*/
private String sortName;
/**
* 排序方式
*/
private String order;
public String getSortName() {
return sortName;
}
public void setSortName(String sortName) {
this.sortName = sortName;
}
public String getOrder() {
return order;
}
public void setOrder(String order) {
this.order = order;
}
}