elasticsearch2.0学习之路(二)java api

在上一篇博客中已经完成了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比如聚合查询,笔者暂时也没去研究,大家可以去学习下,笔者也是刚学,有啥问题的地方欢迎指出,谢谢!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值