在上一篇博客中已经完成了es的安装和集群配置,那么接下来,笔者将介绍下如在java代码中完成对某个索引的类型的文档的增删改查。这个java api的介绍在官网上也有很好的例子,大家可以参考下。
es中的索引就对应数据库,类型就对应着数据库中的表,文档就对应着数据库表中的记录,因此,我们首先得创建一个索引,然后,再创建一个类型,这个类型会包含字段类型信息,然后就可以在这个索引上对此类型的文档进行增删改查了。
下面,笔者将分步介绍:
一、创建EsEnv.java类来保存集群信息
直接贴出代码如下:
package com.qiyongkang.es.client.pool;
/**
* ClassName:EsEnv <br/>
* Date: 2015年11月23日 下午5:24:50 <br/>
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public class EsEnv {
/**
* 集群名
*/
private String clusterName;
/**
* ip集合
*/
private String ip;
/**
* port集合
*/
private String port;
public EsEnv(String clusterName, String ip, String port) {
super();
this.clusterName = clusterName;
this.ip = ip;
this.port = port;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
}
二、创建EsClient.java类来封装客户端的基本信息和操作
直接贴出代码如下:
package com.qiyongkang.es.client.pool;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.optimize.OptimizeRequest;
import org.elasticsearch.action.admin.indices.optimize.OptimizeResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
public class EsClient {
/**
* 日志类
*/
protected final Logger logger = LogManager.getLogger(EsClient.class.getName());
/**
* 集群节点信息集合
*/
private EsEnv esEnv;
/**
* es客户端
*/
private Client client;
/**
* 构造器
* Creates a new instance of EsClient.
*
* @param esEnv
*/
public EsClient(EsEnv esEnv) {
this.esEnv = esEnv;
buildClient();
}
/**
*
* getClient:获取客户端. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public Client getClient() {
return client;
}
/**
*
* addTransport:添一个ip到集群. <br/>
*
* @author qiyongkang
* @param host
* @param port
* @return
* @since JDK 1.6
*/
protected EsClient addTransport(String host, int port) {
try {
((TransportClient) client)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), port));
} catch (UnknownHostException e) {
e.printStackTrace();
logger.error("添加ip地址异常", e);
}
return this;
}
/**
*
* buildClient:生成一个客户端. <br/>
*
* @author qiyongkang
* @since JDK 1.6
*/
private void buildClient() {
//设置
Settings settings = Settings.settingsBuilder().put("cluster.name", esEnv.getClusterName())
.put("transport.tcp.compress", true).build();
//ip数组
String[] arrIp = esEnv.getIp().split(",");
//端口数组
String[] arrPort = esEnv.getPort().split(",");
TransportAddress[] addressArr = new TransportAddress[arrPort.length];
for (int i = 0, size = arrIp.length; i < size; i++) {
String ip = arrIp[i];
int port = 9300;
try {
port = Integer.valueOf(arrPort[i]);
} catch (NumberFormatException e) {
logger.error("port trans error !");
}
try {
addressArr[i] = new InetSocketTransportAddress(InetAddress.getByName(ip), port);
} catch (UnknownHostException e) {
e.printStackTrace();
logger.error("添加ip地址异常", e);
}
}
client = TransportClient.builder().settings(settings).build().addTransportAddresses(addressArr);
logger.info("开辟集群连接,address:{},连接对象:{}", addressArr, client);
}
/**
*
* rebuildClient:重新生成客户端. <br/>
*
* @author qiyongkang
* @since JDK 1.6
*/
public void rebuildClient() {
logger.info("上次client连接发生错误,重新开辟连接!");
if (client != null) {
close();
}
buildClient();
}
/**
*
* getBulkRequestBuilder:获取批量操作的builder. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public BulkRequestBuilder getBulkRequestBuilder() {
return client.prepareBulk();
}
/**
*
* getIndexRequestBuilder:获取索引请求的builder. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public IndexRequestBuilder getIndexRequestBuilder() {
return client.prepareIndex();
}
/**
*
* getUpdateRequestBuilder:获取索引更新请求的builder. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public UpdateRequestBuilder getUpdateRequestBuilder() {
return client.prepareUpdate();
}
/**
*
* getEsSearch:获取搜索请求的builder. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public SearchRequestBuilder getSearchRequestBuilder() {
return client.prepareSearch();
}
/**
*
* esRefresh:刷新. <br/>
*
* @author qiyongkang
* @since JDK 1.6
*/
public void esRefresh() {
client.admin().indices().prepareRefresh().execute().actionGet();
}
/**
* 获取ES服务器的所有打开的索引
*
* @Description:
* @return
*/
public ClusterHealthResponse getClusterHealthResponse() {
return client.admin().cluster().health(Requests.clusterHealthRequest().waitForGreenStatus()).actionGet();
}
/**
* 获取ES服务器的所有索引(包括打开和关闭的索引)
*
* @Description:
* @return
*/
public MetaData getMetaData() {
ClusterState state = client.admin().cluster().prepareState().execute().actionGet().getState();
return state.getMetaData();
}
/**
*
* isExists:判断索引名是否存在. <br/>
*
* @author qiyongkang
* @param indexName
* @return
* @since JDK 1.6
*/
public boolean isExists(String indexName) {
return client.admin().indices().prepareExists(indexName).execute().actionGet().isExists();
}
/**
*
* closeIndex:关闭索引. <br/>
*
* @author qiyongkang
* @param indexName
* @return
* @since JDK 1.6
*/
public boolean closeIndex(String indexName) {
return client.admin().indices().prepareClose(indexName).execute().actionGet().isAcknowledged();
}
/**
*
* closeIndex:打开索引. <br/>
*
* @author qiyongkang
* @param indexName
* @return
* @since JDK 1.6
*/
public boolean openIndex(String indexName) {
return client.admin().indices().prepareOpen(indexName).execute().actionGet().isAcknowledged();
}
/**
*
* deleteIndex:删除索引. <br/>
*
* @author qiyongkang
* @param indexName
* @return
* @since JDK 1.6
*/
public boolean deleteIndex(String indexName) {
return client.admin().indices().prepareDelete(indexName).execute().actionGet().isAcknowledged();
}
/**
*
* createIndex:创建一个索引. <br/>
*
* @author qiyongkang
* @param settings
* @param indexName
* @return
* @since JDK 1.6
*/
public boolean createIndex(Settings settings, String indexName) {
return client.admin().indices().prepareCreate(indexName).setSettings(settings).execute().actionGet()
.isAcknowledged();
}
/**
*
* createAlias:创建索引的别名. <br/>
*
* @author qiyongkang
* @param indexName
* @param aliasName
* @since JDK 1.6
*/
public void createAlias(String indexName, String aliasName) {
client.admin().indices().prepareAliases().addAlias(indexName, aliasName).execute().actionGet();
}
/**
*
* createAlias:删除索引的别名. <br/>
*
* @author qiyongkang
* @param indexName
* @param aliasName
* @since JDK 1.6
*/
public void deleteAlias(String indexName, String aliasName) {
client.admin().indices().prepareAliases().removeAlias(indexName, aliasName).execute().actionGet();
}
/**
*
* putMapping:设置类型的字段映射. <br/>
*
* @author qiyongkang
* @param mappingRequest
* @return
* @since JDK 1.6
*/
public boolean putMapping(PutMappingRequest mappingRequest) {
return client.admin().indices().putMapping(mappingRequest).actionGet().isAcknowledged();
}
/**
*
* optimize:优化索引. <br/>
*
* @author qiyongkang
* @param indexName
* @return
* @since JDK 1.6
*/
public OptimizeResponse optimize(String indexName) {
OptimizeRequest optRequest = new OptimizeRequest(new String[] { indexName });
// optRequest.flush(true);
optRequest.maxNumSegments(1);
OptimizeResponse optResponse = client.admin().indices().optimize(optRequest).actionGet();
return optResponse;
}
/**
* 关闭ES客户端
*
* @Description:
*/
public void close() {
if (client != null) {
logger.info("关闭连接对象成功:{}", client);
client.close();
}
}
}
三、创建PoolableEsFactory.java工厂类来生产和销毁es pool
直接贴出代码如下:
package com.qiyongkang.es.client.pool;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class PoolableEsFactory extends BasePoolableObjectFactory<EsClient> {
private EsEnv esEnv = null;
/**
* 日志类
*/
protected final Logger logger = LogManager.getLogger(PoolableEsFactory.class.getName());
public PoolableEsFactory(EsEnv esEnv) {
super();
this.esEnv = esEnv;
}
@Override
public EsClient makeObject() throws Exception {
EsClient esClient = new EsClient(esEnv);
logger.info("create EsClient:{}! ", esClient);
return esClient;
}
@Override
public void destroyObject(EsClient esClient) throws Exception {
esClient.close();
logger.info("destroyObject EsClient:{}! ", esClient);
super.destroyObject(esClient);
}
@Override
public void passivateObject(EsClient esClient) throws Exception {
logger.info("return to pool");
super.passivateObject(esClient);
}
}
四、创建EsClientPool.java客户端池类来获取es客户端
代码如下:
package com.qiyongkang.es.client.pool;
import org.apache.commons.pool.impl.StackObjectPool;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* ClassName:EsClientPool <br/>
* Date: 2015年11月23日 下午5:13:12 <br/>
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public class EsClientPool {
/**
* 连接池
*/
private StackObjectPool<EsClient> pool = null;
/**
* 日志类
*/
private Logger logger = LogManager.getLogger(EsClientPool.class.getName());
/**
*
* Creates a new instance of EsClientPool.
*
* @param clusterName
* @param ip
* @param port
* @param keepClienNum
*/
public EsClientPool(String clusterName, String ip, String port, int keepClienNum) {
EsEnv esEnv = new EsEnv(clusterName, ip, port);
this.pool = new StackObjectPool<EsClient>(new PoolableEsFactory(esEnv), keepClienNum);
this.logger.info("初始化一个es pool成功...");
}
/**
*
* getEsClient:获取一个es客户端. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public EsClient getEsClient(){
EsClient esClient = null;
try {
esClient = pool.borrowObject();
} catch (Exception e) {
logger.error("create Client error!" , e);
}
return esClient;
}
/**
*
* removeEsClient:移除一个es客户端. <br/>
*
* @author qiyongkang
* @param esClient
* @return
* @since JDK 1.6
*/
public EsClient removeEsClient(EsClient esClient){
try {
pool.returnObject(esClient);
} catch (Exception e) {
logger.error("Client return to pool error!" , e);
}
return esClient;
}
}
接下来,笔者将准备一个model来与es类型中的字段进行对应:
User.java:
package com.qiyongkang.es.model;
import java.util.Date;
/**
* ClassName:User <br/>
* Date: 2015年11月24日 下午5:12:09 <br/>
*
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public class User {
/**
* es自动生成的id
*/
private String esId;
/**
* id
*/
private Long id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 性别,0->男,1->女
*/
private Integer sex;
/**
* 生日,pattern:'yyyy-MM-dd HH:mm:ss'
*/
private Date birthday;
/**
* 起始时间,pattern:'yyyy-MM-dd HH:mm:ss'
*/
private Date startTime;
/**
* 结束时间,pattern:'yyyy-MM-dd HH:mm:ss'
*/
private Date endTime;
/**
* 起始年龄
*/
private Integer startAge;
/**
* 结束年龄
*/
private Integer endAge;
public User() {
}
public User(Long id, String name, Integer age, Integer sex, Date birthday) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.birthday = birthday;
}
public String getEsId() {
return esId;
}
public void setEsId(String esId) {
this.esId = esId;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public Integer getStartAge() {
return startAge;
}
public void setStartAge(Integer startAge) {
this.startAge = startAge;
}
public Integer getEndAge() {
return endAge;
}
public void setEndAge(Integer endAge) {
this.endAge = endAge;
}
@Override
public String toString() {
return "User [esId=" + esId + ",id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", birthday=" + birthday + "]";
}
}
然后,是一个帮助类KeyValue.java:
package com.qiyongkang.es.model;
/**
* ClassName:KeyValue <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2015年11月27日 下午6:15:24 <br/>
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public class KeyValue {
private String key;
private String value;
public KeyValue(String key, String value) {
super();
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "KeyValue [key=" + key + ", value=" + value + "]";
}
}
五、创建一个接口类和抽象类来要求每个es类型操作需要实现的方法
EsEntityService.java:
package com.qiyongkang.es.service;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.xcontent.XContentBuilder;
import com.qiyongkang.es.model.KeyValue;
/**
*
* ES 接口实体(ES 入库实体,ES 查询返回的对象)
*
*
* @param <T>
*/
public interface EsEntityService<T extends Object> {
/**
* 创建T类型的ES mapping的json串
*
* @param typeName
* @return
* @throws IOException
*/
public void createMappingJson() throws IOException;
/**
*
* 创建T类型的ES单条记录的json串
*
* @param t
* T类型的对象
* @return
* @throws IOException
*/
public XContentBuilder buildEntity(T t) throws IOException;
/**
* 将ES key-value集合转换为T类型对象
*
* @param propertiesMap
* ES 查询返回的key-value集合
* @return
*/
public T recoveEntity(Map<String, Object> propertiesMap);
/**
*
* 更新T类型的ES单条记录的json串
*
* @param t
* T类型的对象
* @return
* @throws IOException
*/
public XContentBuilder buildUpdateEntity(T t) throws IOException;
/**
*
* getEsIdByPrimary:根据唯一键查出_id. <br/>
*
* @author qiyongkang
* @param t
* @return
* @since JDK 1.6
*/
public String getEsIdByPrimary(KeyValue dict);
/**
*
* convertSearchResponseToList:将查询结果转为list. <br/>
*
* @author qiyongkang
* @param searchResponse
* @return
* @since JDK 1.6
*/
public List<? extends Object> convertSearchResponseToList(SearchResponse searchResponse);
}
AbstractEntityService.java:
package com.qiyongkang.es.service;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortOrder;
import com.qiyongkang.es.client.pool.EsClient;
import com.qiyongkang.es.model.KeyValue;
/**
* ClassName:AbstractEntityService <br/>
* Date: 2015年11月27日 上午9:49:33 <br/>
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public abstract class AbstractEntityService<T> {
protected EsClient esclient = null;
/**
* 索引名
*/
protected String indexName;
/**
* 类型名
*/
protected String typeName;
/**
* 日志类
*/
protected static Logger logger = LogManager.getLogger(AbstractEntityService.class);
/**
*
* 构造器
*
* @param client
*/
public AbstractEntityService(EsClient client, String indexName, String typeName) {
this.esclient = client;
this.indexName = indexName;
this.typeName = typeName;
}
/**
*
* getEsIdByPrimary:根据唯一键查出_id. <br/>
*
* @author qiyongkang
* @param dict
* @return
* @since JDK 1.6
*/
public String getEsIdByPrimary(KeyValue dict) {
String esId = null;
SearchRequestBuilder srb = this.esclient.getSearchRequestBuilder().setIndices(this.indexName).setTypes(this.typeName);
BoolQueryBuilder bool = QueryBuilders.boolQuery();
//id
if (dict.getValue() != null) {
bool.must(QueryBuilders.termQuery(dict.getKey(), dict.getValue()));
}
SearchResponse searchResponse = srb.setPostFilter(bool)
.addSort(dict.getKey(), SortOrder.ASC)
.execute().actionGet();
SearchHit[] arrHits = searchResponse.getHits().getHits();
if (arrHits != null && arrHits.length > 0) {
esId = arrHits[0].getId();
}
logger.info("唯一键:{}的_id为{}", dict, esId);
return esId;
}
/**
*
* insertBulkSize:分批插入. <br/>
*
* @author qiyongkang
* @param bulkRequest
* @since JDK 1.6
*/
@SuppressWarnings("rawtypes")
protected void insertBulkSize(BulkRequestBuilder bulkRequest) {
List<ActionRequest> actionRequestList = null;
//更新
BulkResponse response = bulkRequest.execute().actionGet();
if (response.hasFailures()) {
logger.error("更新失败:{}", response.buildFailureMessage());
} else {
logger.info("批量更新成功,数目为{}", bulkRequest.request().requests().size());
}
//清空
actionRequestList = bulkRequest.request().requests();
actionRequestList.clear();
}
}
六、创建User类的服务接口和实现类
EsUserService.java:
package com.qiyongkang.es.service;
import java.util.List;
import com.qiyongkang.es.model.KeyValue;
import com.qiyongkang.es.model.User;
import com.qiyongkang.es.util.Page;
/**
* ClassName:EsUserService <br/>
* Date: 2015年11月27日 上午10:20:11 <br/>
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public interface EsUserService extends EsEntityService<User> {
/**
*
* getEntityById:根据id获取实体. <br/>
*
* @author qiyongkang
* @param id
* @return
* @since JDK 1.6
*/
public User getEntityById(int id);
/**
*
* getPageModel:分页查询. <br/>
*
* @author qiyongkang
* @param user
* @param curretPage
* @param pageSize
* @return
* @since JDK 1.6
*/
public Page<User> getPageModel(User user, int curretPage, int pageSize);
/**
*
* singleInsert:单个新增. <br/>
*
* @author qiyongkang
* @param user
* @since JDK 1.6
*/
public void singleInsert(User user);
/**
*
* batchInsert:批量新增. <br/>
*
* @author qiyongkang
* @param userList
* @since JDK 1.6
*/
public void batchInsert(List<User> userList);
/**
*
* singleDelete:单个删除. <br/>
*
* @author qiyongkang
* @param id
* @since JDK 1.6
*/
public void singleDelete(KeyValue dict);
/**
*
* singleUpdate:单个更新. <br/>
*
* @author qiyongkang
* @param user
* @since JDK 1.6
*/
public void singleUpdate(User user);
/**
*
* batchUpdate:批量更新. <br/>
*
* @author qiyongkang
* @param updateList
* @since JDK 1.6
*/
public void batchUpdate(List<User> updateList);
}
实现类EsUserImpl.java:
package com.qiyongkang.es.service.impl;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortOrder;
import com.qiyongkang.es.client.pool.EsClient;
import com.qiyongkang.es.model.KeyValue;
import com.qiyongkang.es.model.User;
import com.qiyongkang.es.service.AbstractEntityService;
import com.qiyongkang.es.service.EsUserService;
import com.qiyongkang.es.util.DateUtil;
import com.qiyongkang.es.util.Page;
/**
* ClassName:EsUserImpl <br/>
* Date: 2015年11月24日 下午5:11:52 <br/>
*
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public class EsUserImpl extends AbstractEntityService<User>implements EsUserService {
/**
* 日志类
*/
protected static Logger logger = LogManager.getLogger(EsUserImpl.class);
/**
*
* 构造器
*
* @param client
*/
public EsUserImpl(EsClient client) {
super(client, "um", "user");
}
/**
*
* 创建类型的字段json映射.
*
* @throws IOException
* @see com.qiyongkang.es.service.EsEntityService#createMappingJson()
*/
@Override
public void createMappingJson() throws IOException {
XContentBuilder xContentBuilder = null;
xContentBuilder = jsonBuilder().startObject().startObject(typeName).startObject("_source")
.field("enabled", true).endObject().startObject("_all").field("enabled", true).endObject()
.startObject("properties").startObject("id").field("type", "long").field("index", "not_analyzed")
.endObject().startObject("name").field("type", "string").endObject().startObject("age")
.field("type", "integer").endObject().startObject("sex").field("type", "integer").endObject()
.startObject("birthday").field("type", "date").field("format", "yyyy-MM-dd HH:mm:ss").endObject()
.endObject().endObject().endObject();
logger.info("开始创建mappingJson:{}", xContentBuilder);
PutMappingRequest mappingRequest = Requests.putMappingRequest(indexName).type(typeName).source(xContentBuilder);
boolean flag = this.esclient.putMapping(mappingRequest);
logger.info("创建索引{}的类型{}的映射是否成功:{}", indexName, typeName, flag);
}
/**
*
* 新增json.
*
* @param t
* @return
* @throws IOException
* @see com.qiyongkang.es.service.EsEntityService#buildEntity(java.lang.Object)
*/
@Override
public XContentBuilder buildEntity(User t) throws IOException {
XContentBuilder source = XContentFactory.jsonBuilder().startObject().field("id", t.getId())
.field("name", t.getName()).field("age", t.getAge()).field("sex", t.getSex())
.field("birthday", DateUtil.dateToYMDHMSStr(t.getBirthday())).endObject();
logger.info("build entity:{}", source);
return source;
}
/**
*
* 将单条文档映射为对应的实体.
*
* @param propertiesMap
* @return
* @see com.qiyongkang.es.service.EsEntityService#recoveEntity(java.util.Map)
*/
@Override
public User recoveEntity(Map<String, Object> propertiesMap) {
User user = new User();
for (String key : propertiesMap.keySet()) {
if ("id".equals(key)) {
user.setId(Long.valueOf(propertiesMap.get(key).toString()));
} else if ("name".equals(key)) {
user.setName(propertiesMap.get(key).toString());
} else if ("age".equals(key)) {
user.setAge(Integer.valueOf(propertiesMap.get(key).toString()));
} else if ("sex".equals(key)) {
user.setSex(Integer.valueOf(propertiesMap.get(key).toString()));
} else if ("birthday".equals(key)) {
user.setBirthday(DateUtil.strToYMDHMSDate(propertiesMap.get(key).toString()));
}
}
return user;
}
/**
*
* 更新json.
*
* @param t
* @return
* @throws IOException
* @see com.qiyongkang.es.service.EsEntityService#buildUpdateEntity(java.lang.Object)
*/
@Override
public XContentBuilder buildUpdateEntity(User t) throws IOException {
XContentBuilder source = XContentFactory.jsonBuilder().startObject();
if (t.getName() != null) {
source.field("name", t.getName());
}
if (t.getAge() != null) {
source.field("age", t.getAge());
}
if (t.getSex() != null) {
source.field("sex", t.getSex());
}
if (t.getBirthday() != null) {
source.field("birthday", DateUtil.dateToYMDHMSStr(t.getBirthday()));
}
source.endObject();
return source;
}
/**
*
* 转换ES查找结果为实体集合
*
* @param searchResponse
* ES查找结果对象
* @param esEntity
* 实体
* @return t类型的实体集合
*/
@Override
public List<? extends Object> convertSearchResponseToList(SearchResponse searchResponse) {
SearchHit[] arrHits = searchResponse.getHits().getHits();
List<Object> lstEsEntity = new ArrayList<Object>(arrHits.length);
for (int i = 0, size = arrHits.length; i < size; i++) {
Map<String, Object> propertiesMap = (Map<String, Object>) arrHits[i].getSource();
Object esObject = this.recoveEntity(propertiesMap);
logger.info("成功转换成一个对象:{}", esObject);
lstEsEntity.add(esObject);
}
return lstEsEntity;
}
/**
*
* 根据id查出用户.
*
* @param indexName
* @param typeName
* @param id
* @return
* @see com.qiyongkang.es.service.EsUserService#getEntityById(java.lang.String,
* java.lang.String, int)
*/
@SuppressWarnings("unchecked")
public User getEntityById(int id) {
User user = null;
SearchRequestBuilder srb = this.esclient.getSearchRequestBuilder().setIndices(indexName).setTypes(typeName);
BoolQueryBuilder bool = QueryBuilders.boolQuery();
// id
bool.must(QueryBuilders.termQuery("id", id));
SearchResponse searchResponse = srb.setPostFilter(bool).addSort("id", SortOrder.ASC).execute().actionGet();
List<User> list = (List<User>) convertSearchResponseToList(searchResponse);
long count = searchResponse.getHits().getTotalHits();
logger.info("查出的个数为{}", count);
if (list != null && list.size() > 0) {
user = list.get(0);
String esId = this.getEsIdByPrimary(new KeyValue("id", user.getId().toString()));
user.setEsId(esId);
logger.info("查出的用户为:{}", user);
}
return user;
}
/**
*
* 分页查询.
* @param user
* @param curretPage
* @param pageSize
* @return
* @see com.qiyongkang.es.service.EsUserService#getPageModel(com.qiyongkang.es.model.User, int, int)
*/
@SuppressWarnings("unchecked")
@Override
public Page<User> getPageModel(User user, int curretPage, int pageSize) {
Page<User> page = new Page<User>();
SearchRequestBuilder srb = esclient.getSearchRequestBuilder().setIndices(this.indexName).setTypes(this.typeName);
BoolQueryBuilder bool = QueryBuilders.boolQuery();
//id
if (user.getId() != null) {
bool.must(QueryBuilders.termQuery("id", user.getId()));
}
//name
if (user.getName() != null) {
bool.must(QueryBuilders.wildcardQuery("name", "*" + user.getName() + "*"));
}
//age
if (user.getAge() != null) {
bool.must(QueryBuilders.termQuery("age", user.getAge()));
}
//startAge
if (user.getStartAge() != null) {
bool.must(QueryBuilders.rangeQuery("age").from(user.getStartAge()));
}
//endAge
if (user.getEndAge() != null) {
bool.must(QueryBuilders.rangeQuery("age").to(user.getEndAge()));
}
//sex
if (user.getSex() != null) {
bool.must(QueryBuilders.termQuery("sex", user.getSex()));
}
//birthday
if (user.getBirthday() != null) {
bool.must(QueryBuilders.termQuery("birthday", DateUtil.dateToYMDHMSStr(user.getBirthday())));
}
//startBirth
if (user.getStartTime() != null) {
bool.must(QueryBuilders.rangeQuery("birthday").from(DateUtil.dateToYMDHMSStr(user.getStartTime())));
}
//endBirth
if (user.getEndTime() != null) {
bool.must(QueryBuilders.rangeQuery("birthday").to(DateUtil.dateToYMDHMSStr(user.getEndTime())));
}
SearchResponse searchResponse = srb.setPostFilter(bool)
.setFrom((curretPage - 1) * pageSize)
.setSize(pageSize)
.addSort("id", SortOrder.ASC)
.execute().actionGet();
logger.info("request:{}", srb.toString());
logger.info("response:{}", searchResponse.toString());
List<User> list = (List<User>) this.convertSearchResponseToList(searchResponse);
long count = searchResponse.getHits().getTotalHits();
logger.info("查出的总数为{}", count);
page.setRows(list);
page.setTotal(count);
return page;
}
/**
*
* 单个插入.
*
* @param user
* @see com.qiyongkang.es.service.EsUserService#singleInsert(com.qiyongkang.es.model.User)
*/
@Override
public void singleInsert(User user) {
boolean flag = false;
try {
flag = esclient.getIndexRequestBuilder().setIndex(indexName).setType(typeName)
.setSource(this.buildEntity(user)).execute().actionGet().isCreated();
esclient.esRefresh();
logger.info("插入用户{}是否成功:{}", user, flag);
} catch (IOException e) {
e.printStackTrace();
logger.error("插入用户{}异常", user, e);
}
}
/**
*
* 批量新增.
*
* @param userList
* @see com.qiyongkang.es.service.EsUserService#batchInsert(java.util.List)
*/
@Override
public void batchInsert(List<User> userList) {
logger.info("开始批量插入,总数为{}", userList.size());
// 每次批量插入的个数
int bulkSize = 5000;
BulkRequestBuilder bulkRequest = this.esclient.getBulkRequestBuilder();
try {
// 用于记录循环下标
int percount = 0;
for (int i = 0; i < userList.size(); i++) {
User user = userList.get(i);
XContentBuilder builder = this.buildEntity(user);
IndexRequestBuilder indexRequestBuilder = this.esclient.getIndexRequestBuilder();
indexRequestBuilder.setIndex(indexName);
indexRequestBuilder.setType(typeName);
indexRequestBuilder.setSource(builder);
bulkRequest.add(indexRequestBuilder);
percount++;
if (percount >= bulkSize) {
insertBulkSize(bulkRequest);
percount = 0;
}
}
if (percount > 0) {
insertBulkSize(bulkRequest);
}
// 刷新
esclient.esRefresh();
} catch (Exception e) {
e.printStackTrace();
logger.error("批量插入过程发生异常。。", e);
}
logger.info("批量插入完成");
}
/**
*
* 单个删除.
* @param id
* @see com.qiyongkang.es.service.EsUserService#singleDelete(java.lang.String)
*/
@Override
public void singleDelete(KeyValue dict) {
//先查出_id,然后再删除
String _id = getEsIdByPrimary(dict);
Client client = esclient.getClient();
client.prepareDelete(indexName, typeName, _id).execute().actionGet();
client.admin().indices().prepareRefresh().execute().actionGet();
logger.info("删除_id为{}的用户{}成功", _id, dict.getValue());
}
/**
*
* 单个更新.
* @param user
* @see com.qiyongkang.es.service.EsUserService#singleUpdate(com.qiyongkang.es.model.User)
*/
@Override
public void singleUpdate(User user) {
logger.info("开始更新,更新的内容为:{}", user);
Client client = this.esclient.getClient();
//第一步、根据id查出_id
String esId = this.getEsIdByPrimary(new KeyValue("id", user.getId().toString()));
user.setEsId(esId);
//第二步、更新
try {
client.prepareUpdate().setIndex(this.indexName).setType(this.typeName)
.setId(user.getEsId()).setDoc(
this.buildUpdateEntity(user))
.execute().actionGet();
//刷新
this.esclient.esRefresh();
logger.info("更新成功:{}", user);
} catch (IOException e) {
e.printStackTrace();
logger.error("更新 发生异常", e);
}
}
/**
*
* 批量更新.
* @param updateList
* @see com.qiyongkang.es.service.EsUserService#batchUpdate(java.util.List)
*/
@Override
public void batchUpdate(List<User> updateList) {
//第一步,查出要更新用户的_id并设置
for (User user : updateList) {
String esId = this.getEsIdByPrimary(new KeyValue("id", user.getId().toString()));
user.setEsId(esId);
}
//第二步,批量更新
logger.info("开始批量更新,总数为{}", updateList.size());
//每次批量更新的个数
int bulkSize = 5000;
BulkRequestBuilder bulkRequest = esclient.getBulkRequestBuilder();
try {
//用于记录循环下标
int percount = 0;
for (int i = 0; i < updateList.size(); i++) {
User user = updateList.get(i);
XContentBuilder builder = this.buildUpdateEntity(user);
UpdateRequestBuilder updateRequestBuilder = esclient.getUpdateRequestBuilder();
updateRequestBuilder.setIndex(indexName);
updateRequestBuilder.setType(typeName);
updateRequestBuilder.setId(user.getEsId());
updateRequestBuilder.setDoc(builder);
bulkRequest.add(updateRequestBuilder);
percount++;
if( percount >= bulkSize ){
insertBulkSize(bulkRequest);
percount = 0;
}
}
if (percount > 0 ) {
this.insertBulkSize(bulkRequest);
}
//刷新
this.esclient.esRefresh();
} catch (Exception e) {
e.printStackTrace();
logger.error("批量插入过程发生异常。。", e);
}
logger.info("批量更新完成");
}
}
七、创建测试类TransportClientTest.java来完成es的java api操作
TransportClientTest.java代码如下:
package com.qiyongkang.es.test;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.settings.Settings;
import com.qiyongkang.es.client.pool.EsClient;
import com.qiyongkang.es.client.pool.EsClientPool;
import com.qiyongkang.es.model.KeyValue;
import com.qiyongkang.es.model.User;
import com.qiyongkang.es.service.EsUserService;
import com.qiyongkang.es.service.impl.EsUserImpl;
import com.qiyongkang.es.util.DateUtil;
import com.qiyongkang.es.util.Page;
/**
* ClassName:TransportClientTest <br/>
* Date: 2015年11月20日 上午9:47:45 <br/>
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
public class TransportClientTest {
/**
* 日志类
*/
private static Logger logger = LogManager.getLogger(TransportClientTest.class.getName());
public static void main(String[] args) {
EsClientPool pool = null;
EsClient esclient = null;
try {
//初始化一个pool
pool = new EsClientPool("myCluster", "172.31.26.200,172.31.26.222", "9300,9300", 20);
logger.info("初始化一个es pool成功:{}", pool);
//获取一个客户端
esclient = pool.getEsClient();
logger.info("获取一个客户端:{}", esclient);
//创建一个EsUserImpl实现类
EsUserService esUserService = new EsUserImpl(esclient);
logger.info("创建一个user服务类:{}", esUserService);
//操作开始时间:
Date startTime = new Date();
long startMilli = startTime.getTime();
logger.info("操作开始时间:{}", DateUtil.dateToYMDHMSStr(startTime));
/***************索引********************/
//创建一个索引
createIndex(esclient, "usermanage");
//删除一个索引
deleteIndex(esclient, "usermanage");
//关闭一个索引
closeIndex(esclient, "usermanage");
//开启一个索引
openIndex(esclient, "um");
//判断一个索引名是否存在
// isExistIndex(esclient, "um");
/***************索引的别名********************/
//创建一个索引的别名
createAlias(esclient, "usermanage", "um");
//删除一个索引的别名
deleteAlias(esclient, "usermanage", "um");
/***************Mapping********************/
//创建MappingJson
esUserService.createMappingJson();
/***************添加********************/
//单个添加
esUserService.singleInsert(new User(1L, "qiyongkang1", 1, 1, DateUtil.strToYMDHMSDate("2015-11-1 11:11:11")));
//批量添加
Date date = DateUtil.strToYMDHMSDate("2015-11-1 11:11:11");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
List<User> userList = new ArrayList<User>();
for (int i = 1; i <= 100000; i++) {
User user = new User();
user.setId(Long.valueOf(i));
user.setName("qiyongkang" + i);
user.setAge(i);
user.setSex(i % 2 == 0 ? 0 : 1);
calendar.add(Calendar.HOUR_OF_DAY, 1);
user.setBirthday(calendar.getTime());
userList.add(user);
}
logger.info("用户集合大小:{}", userList.size());
esUserService.batchInsert(userList);
/***************更新********************/
//单个更新
User user = new User();
user.setId(1L);
user.setBirthday(DateUtil.strToYMDHMSDate("1992-10-11 11:11:11"));
user.setAge(23);
user.setSex(0);
esUserService.singleUpdate(user);
//批量更新
List<User> updateList = new ArrayList<User>();
updateList.add(new User(1L, "qiyongkang1u", 254, 0, null));
updateList.add(new User(2L, "qiyongkang2u", 254, 0, null));
updateList.add(new User(3L, "qiyongkang3u", 254, 0, null));
esUserService.batchUpdate(updateList);
/***************查询********************/
//分页查询
//条件设置
User userCondition = new User();
// user.setId(1L);
// user.setSex(0);
// user.setName("qiyongkang5555");
// user.setAge(10);
// user.setBirthday(DateUtil.strToYMDHMSDate("2015-11-25 11:11:11"));
// user.setStartTime(DateUtil.strToYMDHMSDate("2015-11-25 11:11:11"));
// user.setEndTime(DateUtil.strToYMDHMSDate("2015-11-25 22:11:11"));
// user.setStartAge(12);
// user.setEndAge(18);
Page<User> page = esUserService.getPageModel(userCondition, 1, 20);
logger.info("********user list***********");
for (User u : page.getRows()) {
logger.info(u);
}
logger.info("********user list***********");
//根据id查实体
esUserService.getEntityById(1000);
/***************删除********************/
//删除
esUserService.singleDelete(new KeyValue("id", "1000"));
//操作结束时间
Date endTime = new Date();
long endMilli = endTime.getTime();
logger.info("操作结束时间:{}", DateUtil.dateToYMDHMSStr(endTime));
logger.info("总耗时:{}毫秒。", endMilli - startMilli);
} catch (Exception e) {
e.printStackTrace();
logger.error("es操作出错。", e);
} finally {
//关闭客户端
if (esclient != null) {
esclient.close();
pool.removeEsClient(esclient);
}
}
}
/**
*
* isExistIndex:判断索引名是否存在. <br/>
*
* @author qiyongkang
* @param client
* @param indexName
* @since JDK 1.6
*/
public static void isExistIndex(EsClient client, String indexName) {
boolean isExist = client.isExists(indexName);
logger.info("{}索引是否存在:{}", indexName, isExist ? "存在" : "不存在");
}
/**
*
* openIndex:开启索引. <br/>
*
* @author qiyongkang
* @param client
* @param string
* @since JDK 1.6
*/
public static void openIndex(EsClient client, String indexName) {
client.openIndex(indexName);
logger.info("开启索引{}成功", indexName);
}
/**
*
* closeIndex:关闭索引. <br/>
*
* @author qiyongkang
* @param client
* @param string
* @since JDK 1.6
*/
public static void closeIndex(EsClient client, String indexName) {
client.closeIndex(indexName);
logger.info("关闭索引{}成功", indexName);
}
/**
*
* deleteAlias:删除索引的别名. <br/>
*
* @author qiyongkang
* @param client
* @param string
* @param string2
* @since JDK 1.6
*/
public static void deleteAlias(EsClient client, String indexName, String aliasName) {
client.deleteAlias(indexName, aliasName);
logger.info("删除索引{}的别名{}成功", indexName, aliasName);
}
/**
*
* createAlias:创建一个别名. <br/>
*
* @author qiyongkang
* @param client
* @param string
* @since JDK 1.6
*/
public static void createAlias(EsClient client, String indexName, String aliasName) {
client.createAlias(indexName, aliasName);
logger.info("创建索引{}的别名{}成功", indexName, aliasName);
}
/**
*
* deleteIndex:删除索引. <br/>
*
* @author qiyongkang
* @param client
* @since JDK 1.6
*/
public static void deleteIndex(EsClient client, String indexName) {
client.deleteIndex(indexName);
logger.info("删除一个索引成功,索引名:{}", indexName);
}
/**
*
* createIndex:创建一个索引. <br/>
*
* @author qiyongkang
* @since JDK 1.6
*/
public static void createIndex(EsClient client, String indexName) {
Settings settings = Settings.settingsBuilder()
.put("index.number_of_shards", 5)
.put("index.number_of_replicas", 1)
.put("index.compress", true)
.put("index.store.compress.stored", true)
.put("index.store.compress.tv", true)
.put("index.refresh_interval", "60s")
.put("index.translog.flush_threshold_ops", "50000")
.build();
client.createIndex(settings, indexName);
logger.info("创建一个索引成功,索引名:{}", indexName);
}
}
最后,笔者稍作总结,上面笔者都是只贴出了代码,也没给出比较详细的解释,这个大家可以参考着官网的介绍,然后结合笔者贴出的代码,估计就能够看懂了。另外,还有其它java api比如聚合查询,笔者暂时也没去研究,大家可以去学习下,笔者也是刚学,有啥问题的地方欢迎指出,谢谢!