All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.centit.search.service.Impl.ESSearcher Maven / Gradle / Ivy

package com.centit.search.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.centit.search.annotation.ESType;
import com.centit.search.service.ESServerConfig;
import com.centit.search.service.Searcher;
import com.centit.support.algorithm.ListOpt;
import com.centit.support.json.JSONOpt;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.*;

/**
 * Created by codefan on 17-6-12.
 */
public class ESSearcher implements Searcher{
    private static Logger logger = LoggerFactory.getLogger(ESSearcher.class);

    private ESServerConfig config;
    private GenericObjectPool clientPool;

    private  String[] hightPreTags;
    private  String[] hightPostTags;

    private String[] queryFields;
    private Set highlightFields;
    private String[] revertFields;

    public ESSearcher(ESServerConfig config){
        highlightFields = new HashSet<>();
        this.config = config;
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        clientPool =  new GenericObjectPool<>(new PooledTransportClientTactory(config),
                poolConfig);
    }

    // 定义索引的映射类型
    public void initTypeFields(Class ... objTypes) {
         if(objTypes!=null){
             Set rf = new HashSet<>();
             //rf.add("_type");//添加这个必须返回的保留字段
             Set qf = new HashSet<>();
             for(Class objType : objTypes) {
                 Field[] objFields = objType.getDeclaredFields();
                 for(Field field :objFields){
                     if(field.isAnnotationPresent(ESType.class)){
                         ESType esType =
                                field.getAnnotation(ESType.class);
                         if(esType.query()){
                            qf.add(field.getName());
                         }
                         if(esType.highlight()){
                            highlightFields.add(field.getName());
                         }
                         if(esType.revert()){
                            rf.add(field.getName());
                         }
                     }
                 }//end of for
             }
             if(rf.size()>0) {
                 revertFields = new String[rf.size()];
                 int i=0;
                 for(String fn : rf){
                     revertFields[i] = fn;
                     i++;
                 }
            }

             if(qf.size()>0) {
                 queryFields = new String[qf.size()];
                 int i=0;
                 for(String fn : qf){
                     queryFields[i] = fn;
                     i++;
                 }
             }
        }
    }

    public List> esSearch(QueryBuilder queryBuilder, int pageNo, int pageSize){
        TransportClient client = null;
        try {
            client = clientPool.borrowObject();
            List> retList = new ArrayList<>();
            /*IndicesExistsResponse indicesExistsResponse = client.admin().indices()
                    .exists(new IndicesExistsRequest(config.getIndexName()))
                    .actionGet();
            if (!indicesExistsResponse.isExists()){
                json.put("error","索引不存在");
                retList.add(json);
                return retList;
            }*/
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            for(String hf : highlightFields) {
                highlightBuilder.field(hf);
            }
            highlightBuilder.preTags(this.hightPreTags).postTags(this.hightPostTags);

            SearchResponse actionGet = client
                    .prepareSearch(config.getIndexName())
                    .setQuery(queryBuilder)
                    .highlighter(highlightBuilder)
                    //                .addSort("optTag", SortOrder.DESC)//跟据具体字段排序
                    .setExplain(true)////explain为true表示根据数据相关度排序,和关键字匹配最高的排在前面
                    .setMinScore(config.getMinScore())
                    .setFrom((pageNo>1)?(pageNo-1)* pageSize:0)//分页偏移量
                    .setSize(pageSize)//页面数据大小
                    .storedFields(revertFields)
                    .execute()
                    .actionGet();
            SearchHits hits = actionGet.getHits();
//            System.out.println("查询到记录数=" + hits.getTotalHits());

            for (SearchHit hit : hits.getHits()){
                JSONObject json = new JSONObject();
                for (Map.Entry field : hit.getFields().entrySet()){
                    List objValues = field.getValue().getValues();
                    if(objValues!=null && objValues.size()>0) {
                        if (objValues.size() == 1) {
                            json.put(field.getKey(), objValues.get(0));
                        } else {
                            json.put(field.getKey(), objValues);
                        }
                    }
                }
                //Highlight
                if(hit.getHighlightFields()!=null) {
                    StringBuilder content = new StringBuilder("");
                    for (Map.Entry highlight : hit.getHighlightFields().entrySet()) {
                        HighlightField  highlightField = highlight.getValue();
//                        content.append(highlight.getKey()).append(":");
                        if (highlightField!= null) {
                            for (Text t : highlightField.fragments()) {
                                content.append(t.string()/*.replace("\n", "")*/);
                            }
                        }
                        content.append("\n");
                    }
                    json.put("highlight", content);
                }
                json.put("_score", hit.getScore());
                //hit.type()
                String hitType = hit.getType();
                if(hitType!=null){//获取返回对象的类型
                    json.put("_type", hitType);
                }
                retList.add(json);
//                System.out.println(json);
            }
            return retList;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }finally {
            if(client!=null)
                clientPool.returnObject(client);
        }
    }


    /**
     * 检索所有文档
     * @param fieldFilter 过滤的文件
     * @param queryWord 检索的关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 返回的list结果集
     */
    @Override
    public List> search(Map fieldFilter, String queryWord, int pageNo, int pageSize){
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if(fieldFilter!=null) {
            for (Map.Entry ent : fieldFilter.entrySet()) {
                /*Class tp = obj.getClass();
                return tp.isArray()?true:obj instanceof Collection;*/
                if (ent.getValue().getClass().isArray()) {
                    queryBuilder.must(QueryBuilders.termsQuery(ent.getKey(), (String[]) ent.getValue()));
                } else if (ent.getValue() instanceof Collection) {
                    queryBuilder.must(QueryBuilders.termsQuery(
                            ent.getKey(), ListOpt.listToArray((Collection)ent.getValue())));
                } else {
                    queryBuilder.must(QueryBuilders.matchQuery(ent.getKey(), ent.getValue()));
                }
            }
        }
        queryBuilder.must(QueryBuilders.multiMatchQuery(
                queryWord,queryFields));
        return esSearch( queryBuilder,  pageNo,  pageSize);
    }

    /**
     * 检索所有文档
     * @param queryWord 检索的关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 返回的list结果集
     */
    @Override
    public List> search(String queryWord, int pageNo, int pageSize) {
        return search(null,queryWord,pageNo,pageSize);
    }


    /**
     * 检索某一个系统
     * @param optId 所属业务id
     * @param queryWord 检索的关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 返回的list结果集
     */
    @Override
    public List> searchOpt(String optId, String queryWord, int pageNo, int pageSize) {
         return search(JSONOpt.createHashMap("optId", optId),
                queryWord,pageNo,pageSize);
    }


    /**
     * 根据文档所属 人员来检索
     * @param owner 所属人员
     * @param queryWord 检索的关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 返回list结果集
     */
    @Override
    public List> searchOwner(String owner, String queryWord, int pageNo, int pageSize) {
        return search(JSONOpt.createHashMap("userCode", owner),
                queryWord,pageNo,pageSize);
    }


    /**
     * 根据文档所属 人员 业务来检索
     * @param owner 所属人员
     * @param optId 所属业务id
     * @param queryWord 检索的关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 返回list结果集
     */
    @Override
    public List> searchOwner(String owner, String optId, String queryWord, int pageNo, int pageSize){
        return search(JSONOpt.createHashMap("userCode", owner,"optId", optId),
                queryWord,pageNo,pageSize);
    }

    /**
     * 根据文档所属机构来检索
     * @param units 文档所属机构
     * @param queryWord 检索的关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 返回list结果集
     */
    @Override
    public List> searchUnits(String[] units, String queryWord, int pageNo, int pageSize) {
        return search(JSONOpt.createHashMap("unitCode", units),
                queryWord,pageNo,pageSize);
    }


    /**
     * 根据文档所属机构 业务 关键字 来检索
     * @param units 文档所属机构
     * @param optId 所属业务id
     * @param queryWord 检索的关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 返回list结果集
     */
    @Override
    public List> searchUnits(String[] units, String optId, String queryWord, int pageNo, int pageSize) {
        return search(JSONOpt.createHashMap("optId", optId, "unitCode", units),
                queryWord,pageNo,pageSize);
    }



    public ESSearcher setHightPreTags(String[] hightPreTags) {
        this.hightPreTags = hightPreTags;
        return this;
    }

    public ESSearcher setHightPostTags(String[] hightPostTags) {
        this.hightPostTags = hightPostTags;
        return this;
    }
}