新栋BOOK教你学Elasticsearch(三)基本索引和查询

我们采用2.1版本,2.1版本和1.x版本在api上面有许多不同之处,从1.x版本升级上来的伙伴需要注意,api用法上面都能找到对应的使用。具体的api请参照

https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.1/index.html 

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>2.1.2</version>
</dependency>

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>20.0</version>
</dependency>

建立服务器连接

这一步类似mysql数据库要获取一个DataSource

核心代码

public interface ElasticSearchSource {
    public Client getClient();
}

import com.jd.poplog.dao.elasticsearch.ElasticSearchSource;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class ElasticSearchClientFactory implements ElasticSearchSource{

    private   String clusterName;
    private  Client client;
    static public TransportClient tclient = null;
    public Client getClient() {
        return client;
    }

    /**
     * 创建es client
     * clusterName:集群名字
     * nodeIp:集群中节点的ip地址
     * nodePort:节点的端口
     *
     * @return
     */
    public void init() throws ElasticsearchException {
        synchronized (this){
            Settings settings = Settings.settingsBuilder()
                    .put("cluster.name", clusterName).build();
            //创建集群client并添加集群节点地址
            tclient = TransportClient.builder().settings(settings).build();
            try {
                tclient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.200.189"),9303))//以下是新增加节点
                        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.200.190"),9303));             
                client = tclient;
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } finally {
            }
        }
    }
    public void close() {
        if (null != client) {
            client.close();
        }
    }
    public  void setClusterName(String clusterName) {
        this.clusterName = clusterName;
    }
}

索引数据

有三种方法,使用json字符串,使用map,使用业务bean,参考:

https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.1/java-docs-index.html#java-docs-index-generate-beans

我们介绍使用bean的方法,也是平时开发中最常用的方法,这里包含索引时候的路由字段,当然查询的时候也要根据这个路由字段

public  <T> boolean indexWithBean(T t,String routingId) throws ESException {
        try{
            //用javabean构建json对象
            ObjectMapper mapper = new ObjectMapper();
            byte[] json = mapper.writeValueAsBytes(t);
            //指定索引名称,type名称和documentId(documentId可选,不设置则系统自动生成)创建document
            IndexResponse response = elasticSearchSource.getClient().prepareIndex(indexName, indexType)
                    .setSource(json)
                    .setRouting(routingId)
                    .execute()
                    .actionGet();
            boolean created = response.isCreated();
            return created;
        }catch (Exception e){
            _logger.error("indexWithBean is err.",e);
            throw new ESException("insert into es exception",e);
        }
    }

查询数据

查询稍微复杂一些,涉及分页,高亮,分词等动作,我们一一来描述

分页相关类:

import java.util.List;

public interface PaginatedList<T> extends List<T> {
    boolean isMiddlePage();

    boolean isLastPage();

    boolean isNextPageAvailable();

    boolean isPreviousPageAvailable();

    int getPageSize();

    void setPageSize(int var1);

    int getIndex();

    void setIndex(int var1);

    int getTotalItem();

    void setTotalItem(int var1);

    int getTotalPage();

    int getStartRow();

    int getEndRow();

    int getNextPage();

    int getPreviousPage();

    boolean isFirstPage();
}

import java.util.ArrayList;

public class Page<T> extends ArrayList<T> implements PaginatedList<T> {

    /**
     * 默认每页的记录数量
     */
    public static final int PAGESIZE_DEFAULT = 20;
    /**
     * 每页大小
     */
    private int pageSize;
    /**
     * 当前页。第一页是1
     */
    private int index;

    /**
     * 总记录数
     */
    private int totalItem;
    /**
     * 总页数
     */
    private int totalPage;

    /**
     * 分页后的记录开始的地方
     * 第一条记录是1
     */
    private int startRow;
    /**
     * 分页后的记录结束的地方
     */
    private int endRow;

    /**
     * 默认构造方法
     */
    public Page() {
        repaginate();
    }

    /**
     * 带当前页和页大小的构造方法
     *
     * @param index    当前页
     * @param pageSize 页大小
     */
    public Page(int index, int pageSize) {
        this.index = index;
        this.pageSize = pageSize;
        repaginate();
    }

    /**
     * 表示是不是第一页
     *
     * @return true 是; false 不是
     */
    public boolean isFirstPage() {
        return index <= 1;
    }


    public boolean isMiddlePage() {
        return !(isFirstPage() || isLastPage());
    }


    public boolean isLastPage() {
        return index >= totalPage;
    }


    public boolean isNextPageAvailable() {
        return !isLastPage();
    }

    public boolean isPreviousPageAvailable() {
        return !isFirstPage();
    }

    /**
     * 下一页号
     *
     * @return 取得下一页号
     */
    public int getNextPage() {
        if (isLastPage()) {
            return totalItem;
        } else {
            return index + 1;
        }
    }

    public int getPreviousPage() {
        if (isFirstPage()) {
            return 1;
        } else {
            return index - 1;
        }
    }

    /**
     * Method getPageSize returns the pageSize of this PaginatedArrayList object.
     * <p/>
     * 每页大小
     *
     * @return the pageSize (type int) of this PaginatedArrayList object.
     */

    public int getPageSize() {
        return pageSize;
    }

    /**
     * Method setPageSize sets the pageSize of this PaginatedArrayList object.
     * <p/>
     * 每页大小
     *
     * @param pageSize the pageSize of this PaginatedArrayList object.
     */

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
        repaginate();
    }

    /**
     * Method getIndex returns the index of this PaginatedArrayList object.
     * <p/>
     * 当前页。第一页是1
     *
     * @return the index (type int) of this PaginatedArrayList object.
     */

    public int getIndex() {
        return index;
    }

    /**
     * Method setIndex sets the index of this PaginatedArrayList object.
     * <p/>
     * 当前页。第一页是1
     *
     * @param index the index of this PaginatedArrayList object.
     */

    public void setIndex(int index) {
        this.index = index;
        repaginate();
    }

    /**
     * Method getTotalItem returns the totalItem of this PaginatedArrayList object.
     * <p/>
     * 总记录数
     *
     * @return the totalItem (type int) of this PaginatedArrayList object.
     */

    public int getTotalItem() {
        return totalItem;
    }

    /**
     * Method setTotalItem sets the totalItem of this PaginatedArrayList object.
     * <p/>
     * 总记录数
     *
     * @param totalItem the totalItem of this PaginatedArrayList object.
     */

    public void setTotalItem(int totalItem) {
        this.totalItem = totalItem;
        repaginate();
    }

    /**
     * Method getTotalPage returns the totalPage of this PaginatedArrayList object.
     * <p/>
     * 总页数
     *
     * @return the totalPage (type int) of this PaginatedArrayList object.
     */

    public int getTotalPage() {
        return totalPage;
    }

    /**
     * Method getStartRow returns the startRow of this PaginatedArrayList object.
     * <p/>
     * 分页后的记录开始的地方
     *
     * @return the startRow (type int) of this PaginatedArrayList object.
     */

    public int getStartRow() {
        return startRow;
    }

    /**
     * Method getEndRow returns the endRow of this PaginatedArrayList object.
     * <p/>
     * 分页后的记录结束的地方
     *
     * @return the endRow (type int) of this PaginatedArrayList object.
     */

    public int getEndRow() {
        return endRow;
    }

    /**
     * Method repaginate ...
     */
    private void repaginate() {
        if (pageSize < 1) { //防止程序偷懒,list和分页的混合使用
            pageSize = PAGESIZE_DEFAULT;
        }
        if (index < 1) {
            index = 1;//恢复到第一页
        }
        if (totalItem > 0) {
            totalPage = totalItem / pageSize + (totalItem % pageSize > 0 ? 1 : 0);
            if (index > totalPage) {
                index = totalPage; //最大页
            }
            endRow = index * pageSize;
            //起始startRow应为0
            startRow = endRow - pageSize;
            if (endRow > totalItem) {
                endRow = totalItem;
            }
        }
    }
}

elasticsearch相关

public <T> List<T> getByQueryBean(OpLogQuery opLogQuery,PaginatedList page,String sortField,GetMapping<T> get) {
    List<T> logs = new ArrayList<T>();
    try{
        int startRow= (page.getIndex()-1)*page.getPageSize();

        BoolQueryBuilder builder = buildBoolQuery(opLogQuery);
        QueryBuilder range = QueryBuilders.rangeQuery("opTime").gte(startTime).lt(endTime));
        builder.must(range);

        SearchResponse sResponse = elasticSearchSource.getClient().prepareSearch(indexName1,indexName2,...)//这里可以跨多个索引查询,比如每天一个索引的时候,es的这种api非常方便
                .setTypes(esType)
                .setSearchType(SearchType.QUERY_THEN_FETCH)
                .setQuery(builder)
                //设置排序field
                .addSort(sortField, SortOrder.DESC)
                //设置高亮field
                .addHighlightedField("opContent")
                //设置分页
                .setFrom(startRow).setSize(page.getPageSize())
                .execute()
                .actionGet();
        SearchHits hits = sResponse.getHits();
        int count = (int) hits.getTotalHits();
        page.setTotalItem(count);
        SearchHit[] hitArray = hits.getHits();
        for (int i = 0; i < hitArray.length; i++) {
            SearchHit hit = hitArray[i];
            logs.add(get.mapping(hit));
        }
    }catch (Exception e){
       throw new ESException("query es EXCPTION",e);
    }
    return logs;
}

//通过这个方法可以把查询条件组装到BoolQueryBuilder 中
private BoolQueryBuilder buildBoolQuery(OpLogQuery opLogQuery) {
        Map<String,String> map = new HashMap<String, String>();
        map.put("bizType",opLogQuery.getBusinessType());
        map.put("opObject",opLogQuery.getOperateObj());
        
        BoolQueryBuilder boolQuery = new BoolQueryBuilder();
        for (Map.Entry<String, String> entry : map.entrySet()){
            if (StringUtils.isNotBlank(entry.getValue())&&!DEFAULT_VALUE.equals(entry.getValue())){
//                boolQuery.must(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));
                boolQuery.must(QueryBuilders.prefixQuery(entry.getKey(), entry.getValue()));
            }
        }
        return boolQuery;
    }

关于GetMapping
import org.elasticsearch.search.SearchHit;
public interface GetMapping<T> {
    T mapping(SearchHit hit);
}

调用
elasticSearchDao.getByQueryBean(opLogQuery, page, "opTime", new GetMapping<OpLog>() {
    @Override
    public OpLog mapping(SearchHit hit) {
        OpLog opLog = new OpLog();
        Map<String, Object> fields = hit.getSource();
        opLog.setVenderId(fields.get("venderId").toString());
        opLog.setOpUser(fields.get("opUser").toString());
        opLog.setOpTime(fields.get("opTime").toString());
        
        //设置高亮
        Map<String, HighlightField> result = hit.getHighlightFields();
        if(result.size()>0){
            HighlightField opContentField = result.get("opContent");
            Text[] opContentTexts = opContentField.getFragments();
            for(Text text : opContentTexts){
                opLog.setOpValue(text.string());
            }
        }
        return opLog;
    }
});

到此,Elasticsearch的基本插入和查询就介绍完毕。

参考资料:https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.1/java-docs-index.html

转载于:https://my.oschina.net/wangxindong/blog/820412

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值