目录

  • 一、前言
  • 二、Jest client和Rest client使用
  • 2.1、Rest client方式
  • 三、Rest client方式
  • 3.1、基本操作
  • 3.2、联合查询
  • 3.3、多关键字查询

一、前言

ES有4种客户端,分别是:Jest client、Rest client、Transport client、Node client。
ES支持两种协议
HTTP协议,支持的客户端有Jest client和Rest client
Native Elasticsearch binary协议,也就是Transport client【7.0弃用】和Node client【2.3弃用】
Jest client非官方支持,在ES5.0之前官方提供的客户端只有Transport client、Node client。在5.0之后官方发布Rest client【推荐使用】。

二、Jest client和Rest client使用

2.1、Rest client方式

sptingboot2.0版本引用jar包

<dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.15.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.15.0</version>
        </dependency>
        <!-- elasticsearch -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.15.0</version>
        </dependency>
        <dependency>
            <groupId>com.hankcs</groupId>
            <artifactId>hanlp</artifactId>
            <version>portable-1.7.5</version>
        </dependency>

pom文件配置

#es配置
es.enable=true
es.hostUrl=**
es.port=9200
es.protocol=http
es.connectTimeOut=1000
es.socketTimeOut=30000
es.connectionRequestTimeOut=500
es.maxConnectNum=100
es.maxConnectPerRoute=100
es.username=***
es.password=***

RestHighLevelClient的config如下:

@Configuration
public class ElasticClient {
    @Value("${es.hostUrl}")
    private String hostUrl;
    @Value("${es.port}")
    private int port;
    @Value("${es.protocol}")
    private String protocol;
    @Value("${es.connectTimeOut}")
    private int connectTimeOut;
    @Value("${es.socketTimeOut}")
    private int socketTimeOut;
    @Value("${es.connectionRequestTimeOut}")
    private int connectionRequestTimeOut;
    @Value("${es.maxConnectNum}")
    private int maxConnectNum;
    @Value("${es.maxConnectPerRoute}")
    private int maxConnectPerRoute;
    @Value("${es.username}")
    private String username;
    @Value("${es.password}")
    private String password;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostUrl, port, protocol));
        restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
            @Override
            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                httpClientBuilder.setMaxConnTotal(maxConnectNum);
                httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                return httpClientBuilder;
            }
        });
        //请求配置
        restClientBuilder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
            @Override
            public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
                requestConfigBuilder.setConnectTimeout(connectTimeOut);
                requestConfigBuilder.setSocketTimeout(socketTimeOut);
                requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
                return requestConfigBuilder;
            }
        });
        return new RestHighLevelClient(restClientBuilder);
    }
}

三、Rest client方式

3.1、基本操作

@Data
public abstract class BaseEsDo implements Serializable {
    /**
     * ES的INDEX
     */
    @JSONField(name = "index")
    private String index;
    /**
     * ES唯一值ID
     */
    @JSONField(name = "id")
    private String id;
    /**
     * 创建时间
     */
    @JSONField(name = "create_time", format = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /**
     * 修改时间
     */
    @JSONField(name = "update_time", format = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * 文档状态
     */
    @JSONField(name = "doc_state")
    private Boolean docState;
    /**
     * 文档版本
     */
    @JSONField(name = "doc_version")
    private Integer docVersion;
    /**
     * 文档备注
     */
    @JSONField(name = "doc_remarks")
    private String docRemarks;
    /**
     * 文档查看数量
     */
    @JSONField(name = "doc_view_number")
    private int docViewNumber;
    /**
     * 文档删除状态,默认true
     */
    @JSONField(name = "doc_delete")
    private boolean docDelete = false;
}

AbstractElasticRepository类是封装的常见ES操作

@Repository
@Slf4j
public abstract class AbstractElasticRepository<T extends BaseEsDo> {
    @Autowired
    protected RestHighLevelClient client;
    @Autowired
    private JestClient jestClient; //后续研究


    /**
     * 全量匹配查询 【默认返回10条记录】
     * @param index
     * @return
     */
    public <T extends BaseEsDo> List<T> queryMatchAll(String index, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(index);//指定要查询的索引
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        searchSourceBuilder.query(matchAllQueryBuilder);

        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("花费的时长:" + searchResponse.getTook());
        SearchHits hits = searchResponse.getHits();
        System.out.println(hits.getTotalHits());
        System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * 分页查询、倒序或降序、指定需要返回或者排除的字段
     * sortMap:不能传多个,只能传一个排序
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> pageQuery(String index, int from, int size, Map<String,SortOrder> sortMap, String[] includes,
                                                  String[] excludes, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(index);//指定要查询的索引
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.matchAllQuery());
        //设置分页
        searchSourceBuilder.from(from);
        searchSourceBuilder.size(size);
        //倒序或降序
        if(!sortMap.isEmpty()){
            sortMap.forEach((k,v)->searchSourceBuilder.sort(k,v));
            //    searchSourceBuilder.sort("age", SortOrder.DESC);
        }
        //指定需要返回或者排除的字段
//        String[] includes = {"id", "name"};
//        String[] excludes = {};
        if(null != includes || null != excludes)
            searchSourceBuilder.fetchSource(includes, excludes);
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("花费的时长:" + searchResponse.getTook());
        SearchHits hits = searchResponse.getHits();
        System.out.println(hits.getTotalHits());
        System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * 关键字匹配  【input会分词】
     * 按照要求去相关field去匹配,类似模糊匹配
     * @param index
     * @param input
     * @param fields
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> stringQuery(String index, String input, List<String> fields, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //关键词查找 【会分词】
        QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(input); //默认查询所有field
        if(CollectionUtils.isNotEmpty(fields)){
            fields.forEach(l->queryStringQueryBuilder.field(l));
        }
        searchSourceBuilder.query(queryStringQueryBuilder);
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        System.out.println(hits.getTotalHits());
        System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }


    /**
     * match 查找
     * 【只能是一个字段, 值可以多个,分词后类似模糊查询】
     */
    public <T extends BaseEsDo> List<T> matchQuery(String index, String fieldName, String fieldValue, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //match 查找
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(fieldName, fieldValue);
        matchQueryBuilder.operator(Operator.OR);
        searchSourceBuilder.query(matchQueryBuilder);

        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        System.out.println(hits.getTotalHits());
        System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     *   可以根据字段类型,决定是否使用分词查询,得分最高的在前面。
     *   【支持关键字分词,分词后去多个字段进行匹配】
     * @param index
     * @return
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> multiMatchQuery(String index, String input, String[] fieldNames, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //match 查找
        //例如 QueryBuilders.multiMatchQuery("王者辅助","address", "desc")
        MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(input,fieldNames);
        multiMatchQuery.operator(Operator.OR);
        searchSourceBuilder.query(multiMatchQuery);
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * 精准查询
     *  只匹配一个field字段,传一个input,但不会被分词
     * @param index
     * @param
     * @return
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> termQuery(String index, String fieldName, String input, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //查找
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(fieldName+".keyword",input);
        searchSourceBuilder.query(termQueryBuilder);
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    private QueryBuilder booleanQuery(List<QueryBuilder> termList){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        for(QueryBuilder te : termList){
            boolQueryBuilder.should(te);
        }
        return boolQueryBuilder;
    }
    /**
     * 多个字段精准匹配
     * 使用should方式---测试发现像and结果
     * @param index
     * @param matchMap
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> multiOrTermQuery(String index, Map<String,Object> matchMap, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //查找
        if(!matchMap.isEmpty()){
            List<QueryBuilder> termList = new ArrayList<>();
            matchMap.forEach((k,v)->termList.add(QueryBuilders.termQuery(k, v)));
            searchSourceBuilder.query(booleanQuery(termList));
        }
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * 范围查询
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> rangeQuery(String index, String filed, Object left, Object right, Class<T> clazz)  throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //Range 查找
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(filed);
        rangeQueryBuilder.gte(left);
        rangeQueryBuilder.lt(right);
        searchSourceBuilder.query(rangeQueryBuilder);
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * 多id查询
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> multiIdQuery(String index, List<String> ids, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //多个id 查找
        IdsQueryBuilder idsQueryBuilder = QueryBuilders.idsQuery();
        idsQueryBuilder.addIds((String[])ids.toArray());
        searchSourceBuilder.query(idsQueryBuilder);
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * 高亮查询
     * matchMap: key是关键字,v:是多字段
     */
    public <T extends BaseEsDo> List<T> highlightQuery(String index, String input, String[] fieldNames, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //自定义  多字段高亮 查找
        MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(input,fieldNames);
        multiMatchQuery.operator(Operator.OR);
        searchSourceBuilder.query(multiMatchQuery);

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        for(String te : fieldNames){
            highlightBuilder.field(te);
        }
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.requireFieldMatch(false); //多字段时,需要设置为false
        searchSourceBuilder.highlighter(highlightBuilder);
        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("花费的时长:" + searchResponse.getTook());
        SearchHits hits = searchResponse.getHits();
        System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
        hits.forEach(p -> {
            System.out.println("文档原生信息:" + p.getSourceAsString());
            System.out.println("高亮信息:" + p.getHighlightFields());
//            //获取高亮字段
//            Map<String, HighlightField> highlightFields = p.getHighlightFields();
        });
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     *  模糊查询 --都不会分词
     *  fuzzyQuery: 左右模糊查询 【不分词,fuzziness的参数作用是在查询时,es动态的将查询关键词前后增加或者删除一个词,然后进行匹配】
     *  prefixQuery:前缀查询
     *  通配符查询,支持*和?,?表示单个字符
     * @param index
     * @return
     * @throws IOException
     */
    public <T extends BaseEsDo> List<T> vagueQuery(String index, String input, String fieldName, Integer type, Class<T> clazz) throws IOException{
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(index);
        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        if(type == 1){
            //Fuzzy 查找
            FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery(fieldName, input).fuzziness(Fuzziness.ONE);
            searchSourceBuilder.query(fuzzyQueryBuilder);
        }else if(type == 2){
            PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery(fieldName, input);
            searchSourceBuilder.query(prefixQueryBuilder);
        }else if(type == 3){
            //有点类似  规定好某种格式,进行搜索
            // QueryBuilders.wildcardQuery(“title”, “开*放”)
            //QueryBuilders.wildcardQuery(“title”, “开?放”)
            WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(fieldName, input);
            searchSourceBuilder.query(wildcardQueryBuilder);
        }

        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);
        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<T> list = Arrays.stream(hits.getHits())
                .map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * ik分词
     * @param text 文本
     */
    public List<String> getAnalyze(String text) throws IOException {
        text = text.length() > 100 ? text.substring(0, 100) : text;
        return getAnalyze(text, "ik_max_word");
    }

    /**
     * ik分词
     * @param text     文本
     * @param analyzer 分词器
     */
    public List<String> getAnalyze(String text, String analyzer) throws IOException {

        Request request = new Request("GET", "_analyze");
        JSONObject entity = new JSONObject();
        entity.put("analyzer", analyzer);
        entity.put("text", text);
        request.setJsonEntity(entity.toJSONString());
        Response response = this.client.getLowLevelClient().performRequest(request);
        JSONObject tokens = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
        JSONArray arrays = tokens.getJSONArray("tokens");
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < arrays.size(); i++) {
            JSONObject obj = JSON.parseObject(arrays.getString(i));
            list.add(obj.getString("token"));
        }
        return list;
    }
}

具体业务类TestElasticRepository

@Repository
public class TestElasticRepository extends AbstractElasticRepository<TestEsDo> {
    public RestHighLevelClient getClient(){
        return client;
    }
}

常见的使用方式

public void queryMatchAll(){
        try{
            testElasticRepository.queryMatchAll(TEST_INDEX,TestEsDo.class);
            Map<String,SortOrder> sortMap = new HashMap<>();
            sortMap.put("age",SortOrder.DESC);
            testElasticRepository.pageQuery(TEST_INDEX,1,3,sortMap,null,null,TestEsDo.class);

            testElasticRepository.stringQuery(TEST_INDEX,"城市",Arrays.asList("description","test_name"),TestEsDo.class);
            testElasticRepository.termQuery(TEST_INDEX,"test_name","上海",TestEsDo.class);
            List<String> wordList = testElasticRepository.getAnalyze("历史城市");
            System.out.println("wordList: "+JSON.toJSONString(wordList)); //wordList: ["历史","城市"]
            //这里匹配就是根据分词然后查询description字段
           testElasticRepository.matchQuery(TEST_INDEX,"description","历史城市",TestEsDo.class);
            String[] vaStr1 = new String[]{"description","test_name"};
            //"京城市"分词后,然后对description、test_name字段进行匹配查询,得分高的在前面,默认返回10条
            testElasticRepository.multiMatchQuery(TEST_INDEX,"京城市",vaStr1,TestEsDo.class);
            testElasticRepository.highlightQuery(TEST_INDEX,"京城市",vaStr1,TestEsDo.class);
            testElasticRepository.vagueQuery(TEST_INDEX,"历史","description",1,TestEsDo.class);

            Map<String,Object> matchMap5 = new HashMap<>();
            matchMap5.put("age",200);
            matchMap5.put("test_name","南京");
            testElasticRepository.multiOrTermQuery(TEST_INDEX,matchMap5,TestEsDo.class);


        }catch (Exception e){
            log.error("queryMatchAll e:{}",e.getMessage());
        }

    }

3.2、联合查询

一般ES的步骤是:

SearchRequest searchRequest = new SearchRequest(index); //指定要查询的索引
 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //创建 SearchSourceBuilder条件构造
 MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(input,fieldNames); //match 查找条件
 multiMatchQuery.operator(Operator.OR);
 searchSourceBuilder.query(multiMatchQuery); //match查找条件 赋给 SearchSourceBuilder
 searchRequest.source(searchSourceBuilder); //将 SearchSourceBuilder 添加到 SearchRequest中

BoolQueryBuilder查询

must: 文档必须匹配must所包括的查询条件,相当于 “AND”
 should: 文档应该匹配should所包括的查询条件其中的一个或多个,相当于 “OR”
 must_not: 文档不能匹配must_not所包括的该查询条件,相当于“NOT”

现在有需求查询两个表,它们有各自的条件

public void multiTableQuery(String searchContent,String knowledgeClassificationNo,String startTe,String endTe){

        BoolQueryBuilder boolBuilder = new BoolQueryBuilder();
        boolBuilder.should(getKnowledgeBoolBuilder(searchContent,knowledgeClassificationNo,startTe,endTe));
        boolBuilder.should(getFileBoolBuilder(searchContent,knowledgeClassificationNo,startTe,endTe));

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolBuilder);  //设置查询条件
        boolBuilder.should().forEach(k->{
            BoolQueryBuilder te = (BoolQueryBuilder)k;
            log.info("boolBuilder:{}", JSON.toJSONString(te.must()));
        });

        //设置高亮显示
        ElasticQueryBuilder.setHighlight(searchSourceBuilder);
        //设置分页
        ElasticQueryBuilder.setPage(searchSourceBuilder, new Pagination());
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.source(searchSourceBuilder);
        // es搜索
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits hits = searchResponse.getHits();
            System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
            hits.forEach(p -> {
                System.out.println("文档原生信息:" + p.getSourceAsString());
                System.out.println("高亮信息:" + p.getHighlightFields());
//            //获取高亮字段
//            Map<String, HighlightField> highlightFields = p.getHighlightFields();
            });
            for (SearchHit searchHit : hits.getHits()) {
                Map<String, Object> map = searchHit.getSourceAsMap();
                System.out.println("multiQuery:" + JSON.toJSONString(map));
            }

        }catch (Exception e){

        }

    }

    private BoolQueryBuilder getKnowledgeBoolBuilder(String searchContent,String knowledgeClassificationNo,String startTe,String endTe){
        //查询条件
        BoolQueryBuilder knowledgeBoolBuilder = QueryBuilders.boolQuery();
        //knowledgeBoolBuilder must()
        knowledgeBoolBuilder.must(ElasticQueryBuilder.term("sid", "665555"));

        MultiMatchQueryBuilder kMultiMatchQueryBuilder = new MultiMatchQueryBuilder(searchContent,
                "name", "tag.tag_name", "desc").boost(3);
        //knowledgeBoolBuilder must()
        knowledgeBoolBuilder.must(kMultiMatchQueryBuilder);
        //knowledgeBoolBuilder must()
        knowledgeBoolBuilder.must(ElasticQueryBuilder.term("type.classification_no.keyword", knowledgeClassificationNo));
        //knowledgeBoolBuilder must()
        List<String> tagNos = Arrays.asList("654444","333555","55433");
        knowledgeBoolBuilder.must(ElasticQueryBuilder.termsKeyword("tag.tag_no", tagNos));
        Date startTime = TimeUtil.stringToDate(startTe,"yyyy-MM-dd HH:mm:ss");
        Date endTime = TimeUtil.stringToDate(endTe,"yyyy-MM-dd HH:mm:ss");
        RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("create_time.keyword").gte(startTime).lte(endTime);
        //knowledgeBoolBuilder must()
        knowledgeBoolBuilder.must(rangeQueryBuilder);
        //knowledgeBoolBuilder must()
        knowledgeBoolBuilder.must(ElasticQueryBuilder.term("doc_delete", false));
        //knowledgeBoolBuilder must()
        knowledgeBoolBuilder.must(QueryBuilders.termQuery("_index", "knowledge"));
        return knowledgeBoolBuilder;
    }

3.3、多关键字查询

输入是多个关键字,不分词,对某个ES字段进行查询

ES表test_word_matrix的结构如下,输入List<>,对wordMatrix字段进行匹配,按照top顺序高低返回。

{
 “_index”: “test_word_matrix”,
 “_type”: “_doc”,
 “_id”: “a4e780c2-2744-46de-8f66-5462e3b7e051”,
 “_version”: 1,
 “_seq_no”: 0,
 “_primary_term”: 1,
 “found”: true,
 “_source”: {
 “answer”: “工作原理是:接完可往里面倒胃口我们的思考时代大厦”,
 “basic_problem”: “MG ONE车型中ETC系统的激活原理”,
 “create_time”: “2023-07-17 16:53:21”,
 “doc_delete”: false,
 “doc_view_number”: 0,
 “id”: “a4e780c2-2744-46de-8f66-5462e3b7e051”,
 “index”: “test_word_matrix”,
 “origin_problem”: “MGONE ETC系统 激活原理”,
 “update_time”: “2023-07-17 16:53:21”,
 “wordMatrix”: [
 “中”,
 “ETC”,
 “车型”,
 “系统”,
 “ONE”,
 “激活”,
 “原理”,
 “MG”
 ]
 }
 }
public String queryWordMatrix(List<String> wordMa){
        //查询条件
        BoolQueryBuilder wordMatrixBuiler = QueryBuilders.boolQuery();

        wordMatrixBuiler.must(ElasticQueryBuilder.termsKeyword("wordMatrix", wordMa));
        wordMatrixBuiler.must(QueryBuilders.termQuery("_index", TEST_WORD_MATRIX_INDEX));

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(wordMatrixBuiler);  //设置查询条件
        //设置高亮显示
        ElasticQueryBuilder.setHighlight(searchSourceBuilder);
        //设置分页
        ElasticQueryBuilder.setPage(searchSourceBuilder, new Pagination());
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.source(searchSourceBuilder);
        // es搜索
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits hits = searchResponse.getHits();
            System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
            hits.forEach(p -> {
                System.out.println("文档原生信息:" + p.getSourceAsString());
                System.out.println("高亮信息:" + p.getHighlightFields());
//            //获取高亮字段
//            Map<String, HighlightField> highlightFields = p.getHighlightFields();
            });
            for (SearchHit searchHit : hits.getHits()) {
                Map<String, Object> map = searchHit.getSourceAsMap();
                System.out.println("multiQuery:" + JSON.toJSONString(map));
            }
            return JSON.toJSONString(hits.getHits());
        }catch (Exception e){

        }
        return null;
    }