RestHighLevelClient操作

       <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.15.2</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.15.2</version>
        </dependency>

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class RestClientConfig  {

    @Value("${es.iphosts:localhost:9200}")
    private String ipHosts;
    @Value("${es.password:null}")
    private String password;
    @Value("${es.username:null}")
    private String username;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        List<HttpHost> hosts = new ArrayList<>();
        String[] iphostArray = ipHosts.split(";");
        for (int i = 0; i < iphostArray.length; i++) {
            if (StringUtils.isEmpty(iphostArray[i])) {
                continue;
            }
            hosts.add(new HttpHost(iphostArray[i].split(":")[0],
                    Integer.valueOf(iphostArray[i].split(":")[1]),"http"));
        }
        Header[] headers = new BasicHeader[2];
        headers[0] = new BasicHeader("username",username);
        headers[1] = new BasicHeader("password",password);

        RestClientBuilder builder = RestClient.builder(hosts.stream().toArray(HttpHost[]::new))
                .setDefaultHeaders(headers)
                .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
                    @Override
                    public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) {
                        return builder.setConnectTimeout(5000 * 1000)
                                /** 套接字超时(默认为30秒)//更改客户端的超时限制默认30秒现在改为100*1000分钟 */
                                .setSocketTimeout(6000 * 1000); //
                    }
                });
        RestHighLevelClient client =  new RestHighLevelClient(builder);
        return client;
    }
}


import com.alibaba.fastjson.JSONObject;
import com.example.demo.es.entity.Product;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedDoubleTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.List;
import java.util.Map;


@SpringBootTest
public class EsTest {
    @Autowired
    private  RestHighLevelClient client;

//    @Autowired
//    public EsTest(RestHighLevelClient restHighLevelClient){
//        this.client=restHighLevelClient;
//    }

    /**
     *  查看官网的api
     *  https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.17/java-rest-high-create-index.html
     * @throws IOException
     */

    /**
     * 创建索引,使用ik分词器
     * @throws IOException
     */
   @Test
    public void createIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("products");
        request.settings(Settings.builder()
                .put("index.number_of_shards", 3)
                .put("index.number_of_replicas", 2)
        );
        request.mapping(
                "{\n" +
                        "        \"properties\": {\n" +
                        "            \"id\": {\n" +
                        "                \"type\": \"integer\"\n" +
                        "            },\n" +
                        "            \"title\": {\n" +
                        "                \"type\": \"keyword\"\n" +
                        "            },\n" +
                        "            \"price\": {\n" +
                        "                \"type\": \"double\"\n" +
                        "            },\n" +
                        "            \"created_at\": {\n" +
                        "                \"type\": \"date\"\n" +
                        "            },\n" +
                        "            \"description\": {\n" +
                        "                \"type\": \"text\",\n" +
                        "                \"analyzer\":\"ik_max_word\"\n" +
                        "            },\n" +
                        "             \"brand\": {\n" +
                        "                \"type\": \"keyword\"\n" +
                        "            }\n" +
                        "        }\n" +
                        "    }",
                XContentType.JSON);
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse.isAcknowledged());

    }

    /**
     * 插入文档
     * @throws IOException
     */
    @Test
    public void insertDoc() throws IOException {
        IndexRequest request=new IndexRequest("products");

        Product product=new Product();
        product.setId(1);
        product.setTitle("小米手机");
        product.setPrice(1999.9d);
        product.setDescription("小米手机正好");
        request.id(product.getId().toString());
        request.source(JSONObject.toJSONString(product), XContentType.JSON);
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        System.out.println(indexResponse.getResult());

    }

    /**
     * 根据Id文档
     * @throws IOException
     */
    @Test
    public void updateDocById() throws IOException {

        UpdateRequest request=new UpdateRequest();
        request.index("products").id("1");
        Product product=new Product();
        product.setDescription("小米发烧为生");
        request.doc(JSONObject.toJSONString(product), XContentType.JSON);
        UpdateResponse  updateResponse = client.update(request, RequestOptions.DEFAULT);
        System.out.println(updateResponse.getResult());

    }

    /**
     * 根据Id删除文档
     * @throws IOException
     */
    @Test
    public void delDocById() throws IOException {
        //3.删除数据
        DeleteRequest deleteRequest=new DeleteRequest();
        deleteRequest.index("products").id("1");
        DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(deleteResponse.getResult());
    }

    /**
     * 根据Id查询文档
     * @throws IOException
     */
    @Test
    public void getDocById() throws IOException {
        GetRequest getRequest=new GetRequest();
        getRequest.index("products").id("1");
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        System.out.println("查出的数据为:"+ getResponse.getSourceAsString());
    }



    /**
     * 查询所有文档
     * @throws IOException
     */
    @Test
    public void matchAllTest() throws IOException {
        QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
        query(queryBuilder);
    }

    public void query(QueryBuilder queryBuilder )throws IOException{
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("products");
        searchRequest.source(new SearchSourceBuilder().query(queryBuilder));
        System.out.println("查询DSL为:"+searchRequest.source().toString());
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("返回结果为:"+searchRes.toString());
        System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
        System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
        SearchHit[] hits = searchRes.getHits().getHits();
        for (SearchHit hit: hits) {
            System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
        }
        client.close();
    }


    /**
     * 根据关键词term查询
     * @throws IOException
     */
    @Test
    public void termTest() throws IOException {
        QueryBuilder queryBuilder = QueryBuilders.termQuery("description","小米");
        query(queryBuilder);
    }

    /**
     * 范围range查询
     * @throws IOException
     */
    @Test
    public void rangeTest() throws IOException {
        RangeQueryBuilder queryBuilder=QueryBuilders.rangeQuery("price");
        queryBuilder.gte(100);
        queryBuilder.lt(300);
        query(queryBuilder);
    }

    /**
     * 前缀prefix查询
     * @throws IOException
     */
    @Test
    public void prefixTest() throws IOException {
        QueryBuilder queryBuilder = QueryBuilders.prefixQuery("description","小米");
        query(queryBuilder);
    }

    /**
     * 通配符wildcard查询,?匹配一个,*匹配多个
     * title 为keyword,不分词
     * @throws IOException
     */
    @Test
    public void wildcardTest() throws IOException {
        QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("title","*红*");
        query(queryBuilder);
    }


    /**
     * 模糊fuzzy查询
     *
     * fuzzy 模糊查询,最大模糊错误,必须现在0-2之间
     * 1.搜索关键词长度为2,不允许存在模糊
     * 2.搜索关键词长度为3-5,允许一次模糊
     * 3.搜索关键词长度大于5,允许最大2次模糊
     * @throws IOException
     */
    @Test
    public void fuzzyTest() throws IOException {
        FuzzyQueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("title", "红米大机").fuzziness(Fuzziness.TWO);
        query(queryBuilder);
    }


    /**
     * ids查询
     * @throws IOException
     */
    @Test
    public void idsTest() throws IOException {
        QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1","3");
        query(queryBuilder);
    }

    /**
     * multiMatch多字段查询,基于分词器
     * @throws IOException
     */
    @Test
    public void multiMatchTest() throws IOException {
        QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("真棒").field("title").field("description");
        query(queryBuilder);
    }

    /**
     * 分页查询 form 起始位,size条数
     * 排序查询 sort
     * 包含和排查字段
     * @throws IOException
     */
    @Test
    public void pageTest() throws IOException {
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        //默认10条
        query.from(0).size(2);
        query.sort("price", SortOrder.DESC);
        //需要的字段名称
        String[] include={};
        //不需要的字段名称
        String[] exclude={"created_at"};
        query.fetchSource(include,exclude);
        searchRequest.source(query);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
        System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
        SearchHit[] hits = searchRes.getHits().getHits();
        for (SearchHit hit: hits) {
            System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
        }
        client.close();
    }



    /**
     * 高亮查询,不能用matchAllQuery查询
     * @throws IOException
     */
    @Test
    public void  highlightTest() throws IOException {
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.termQuery("description","苹果"));
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        /**
         * 需要高亮的字段
         */
        highlightBuilder.field("title").field("description");
        highlightBuilder.requireFieldMatch(false);
        query.highlighter(highlightBuilder);
        searchRequest.source(query);
        System.out.println("查询DSL为:"+searchRequest.source().toString());
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("返回结果为:"+searchRes.toString());
        System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
        System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
        SearchHit[] hits = searchRes.getHits().getHits();
        for (SearchHit hit: hits) {
            System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
           if(highlightFields.containsKey("description")){
               System.out.println("description高亮的结果:"+highlightFields.get("description").fragments()[0]);
           }
            if(highlightFields.containsKey("title")){
                System.out.println("title高亮的结果:"+highlightFields.get("title").fragments()[0]);
            }
        }
        client.close();
    }



    /**
     * query :精确查询,查询计算文档得分,并根据得分进行返回
     * filter query:过滤查询,用在大数量中筛选出本地查询相关数据,不会计算文档得分,经常使用filter query 结果进行缓存
     * 注意:一旦使用query和filter query 。ES 优先执行filter,然后再执行query
     *  postFilter 中可以搭配term,terms,range,ids,exists
     * @throws IOException
     */
    @Test
    public void  filterTest() throws IOException {
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.termQuery("description","手机"));

        //builder.postFilter(QueryBuilders.rangeQuery("price").gt(100).lt(200));
        //builder.postFilter(QueryBuilders.idsQuery().addIds("1","2"));
        //如果某个字段存在
        builder.postFilter(QueryBuilders.existsQuery("title"));
        searchRequest.source(builder);
        System.out.println("查询DSL为:"+searchRequest.source().toString());
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("返回结果为:"+searchRes.toString());
        System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
        System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
        SearchHit[] hits = searchRes.getHits().getHits();
        for (SearchHit hit: hits) {
            System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
        }
        client.close();
    }


    /**
     * aggs :聚合查询(aggs) -sql中分组
     * @throws IOException
     */
    @Test
    public void  composeTest() throws IOException {
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("title","红米手机"));
        boolQueryBuilder.should(QueryBuilders.rangeQuery("price").gt(100).lt(200));
        builder.query(boolQueryBuilder);
        searchRequest.source(builder);
        System.out.println("查询DSL为:"+searchRequest.source().toString());
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("返回结果为:"+searchRes.toString());
        System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
        System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
        SearchHit[] hits = searchRes.getHits().getHits();
        for (SearchHit hit: hits) {
            System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
        }
        client.close();

    }

    /**
     * aggs :聚合查询(aggs) -sql中分组
     * @throws IOException
     */
    @Test
    public void  aggsTest() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        AggregationBuilder aggregationBuilder = AggregationBuilders.terms("priceGroup").field("price");
        builder.aggregation(aggregationBuilder);

        /**
         * 如果不需要返回查询的结果,size=0
         *      builder.size(0);
         */

        searchRequest.source(builder);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
        }
        Aggregations aggregations = searchRes.getAggregations();
        /**
           因为是根据Price来分组,price是double类型的,所以用ParsedDoubleTerms,适用于k->v这种的
         */
        ParsedDoubleTerms parsedDoubleTerms = aggregations.get("priceGroup");
        List<? extends Terms.Bucket> buckets = parsedDoubleTerms.getBuckets();
        for (Terms.Bucket bucket:buckets){
            System.out.println("key:为"+bucket.getKeyAsString()+",count数量为:"+bucket.getDocCount());
        }
        client.close();

    }


    /**
     * aggs :聚合查询(aggs) -聚合函数max,min,avg,sum
     * @throws IOException
     */
    @Test
    public void  aggsOperateTest() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        AggregationBuilder aggregationBuilder = AggregationBuilders.sum("priceSum").field("price");
        builder.aggregation(aggregationBuilder);

        /**
         * 如果不需要返回查询的结果,size=0
         *      builder.size(0);
         */

        searchRequest.source(builder);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
        }
        Aggregations aggregations = searchRes.getAggregations();

        /**
         max 使用ParsedMax处理
         min 使用ParsedMin处理
         avg 使用 ParsedAvg处理
         sum 使用ParsedSum处理
         */
        ParsedSum parsedSum = aggregations.get("priceSum");
        double sumValue = parsedSum.getValue();
        System.out.println("求和值为:"+sumValue);
        client.close();
    }

 /**
     * collapse :折叠,比如根据菜系折叠,从每个菜系中选前2名好吃的菜
     * <p>
     * 下面是根据价格折叠,然后再每个子域中按照title折叠
     *
     * @throws IOException
     */
    @Test
    public void collapseTest() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder builder = new SearchSourceBuilder();

        QueryBuilder queryBuilder = QueryBuilders.matchQuery("brand", "vivo");
        builder.query(queryBuilder);
        CollapseBuilder collapseBuilder = new CollapseBuilder("price");
        List<InnerHitBuilder> innerHits = new ArrayList<>();
        InnerHitBuilder innerHitBuilder = new InnerHitBuilder();
        innerHitBuilder.setName("r_date");
        innerHitBuilder.addSort(SortBuilders.fieldSort("created_at").order(SortOrder.DESC));
        innerHitBuilder.setSize(10);
        innerHitBuilder.setInnerCollapse(new CollapseBuilder("title"));
        innerHits.add(innerHitBuilder);
        collapseBuilder.setInnerHits(innerHits);
        builder.collapse(collapseBuilder);
        searchRequest.source(builder);
        System.out.println("查询DSL为:" + searchRequest.source().toString());
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
            Map<String, SearchHits> innerHitsRes = hit.getInnerHits();
            for (Map.Entry<String, SearchHits> map : innerHitsRes.entrySet()) {
                String fieldKey = map.getKey();
                SearchHits innerSearchHits = map.getValue();
                SearchHit[] innerHitRes = innerSearchHits.getHits();
                for (SearchHit h : innerHitRes) {
                    System.out.println("collapse field: " + fieldKey + ",id:为" + h.getId() + ",数据为:" + h.getSourceAsString());
                }
            }

        }
        client.close();
    }


    /**
     * aggs :聚合查询(aggs) -top_hits 取分组中的前几位
     *
     * @throws IOException
     */
    @Test
    public void aggsTopHitsTest() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        AggregationBuilder aggregationBuilder = AggregationBuilders.topHits("price_top").sort(SortBuilders.fieldSort("price").order(SortOrder.DESC)).size(2);
        builder.aggregation(aggregationBuilder);

        /**
         * 如果不需要返回查询的结果,size=0
         *      builder.size(0);
         */
        builder.size(0);
        searchRequest.source(builder);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
        }
        Aggregations aggregations = searchRes.getAggregations();
        TopHits topHits = aggregations.get("price_top");
        SearchHits hitsRes = topHits.getHits();

        for (SearchHit hit : hitsRes.getHits()) {
            System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
        }
        client.close();

    }



    /**
     * aggs :聚合查询(aggs) -percentile_ranks 百分比排名
     *
     * 统计手机在不同的价格区间的占比
     * @throws IOException
     */
    @Test
    public void aggsPercentileRanksTest() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("products");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        double[] rankVal={200d,300d,500d};
        PercentileRanksAggregationBuilder aggregationBuilder = AggregationBuilders.percentileRanks("price_ranks",rankVal);
        aggregationBuilder.field("price");
        builder.aggregation(aggregationBuilder);

        /**
         * 如果不需要返回查询的结果,size=0
         *      builder.size(0);
         */
        builder.size(0);
        searchRequest.source(builder);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
        }
        Aggregations aggregations = searchRes.getAggregations();
        PercentileRanks rercentileRanks  = aggregations.get("price_ranks");
        for (Percentile entry : rercentileRanks) {
            double percent = entry.getPercent();    // Percent
            double value = entry.getValue();        // Value
            System.out.println("value:"+value+"percent:"+percent);
        }
        client.close();

    }

 /**
     * 自动补全功能,使用拼音分词器搜索
     *
     * @throws IOException
     */
    @Test
    public void autoCompleteTest() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("stars");
        SearchSourceBuilder builder = new SearchSourceBuilder();

        CompletionSuggestionBuilder completionSuggestionBuilder=new CompletionSuggestionBuilder("name").skipDuplicates(true).size(10);
        completionSuggestionBuilder.prefix("liu");
        SuggestBuilder suggestBuilder=new SuggestBuilder();
        suggestBuilder.addSuggestion("star_name_suggest",completionSuggestionBuilder);
        builder.suggest(suggestBuilder);
        /**
         * 如果不需要返回查询的结果,size=0
         *      builder.size(0);
         */
        builder.size(0);
        /**
         * 不需要Source可以去掉
         */
        builder.fetchSource(false);
        searchRequest.source(builder);
        System.out.println("查询DSL为:" + searchRequest.source().toString());
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);

        CompletionSuggestion
               suggest = searchRes.getSuggest().getSuggestion("star_name_suggest");
        ArrayList<String> list=new ArrayList<>();
        suggest.forEach(c->c.getOptions().forEach(f->
                list.add(   f.getText().toString())
        ));
        list.forEach(System.out::println);
        client.close();

    }

}


自定义打分

根据业务规则来定制排序规则,如果同时使用sort,那么按照sort来排序,脚本无效

     SearchRequest searchRequest = new SearchRequest("products");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.filter(QueryBuilders.termsQuery("brand", "vivo"));
        Map<String, Object> params = new HashMap(8);
        Map<String, Double> scoreMap = new HashMap<>(16);
        scoreMap.put("vivo手机", 2d);
        scoreMap.put("NEX手机", 1.5d);
        scoreMap.put("xplay手机", 1d);
        scoreMap.put("iQOO手机", 3d);
        params.put("scoreMap", scoreMap);

        final String scoreScript =
                "HashMap scoreMap = (HashMap)params.scoreMap;double score = 0d;" +
                        "String title = doc['title'].value;" +
                        "double price = doc['price'].value;" +
                        "double phoneScore = 0d; " +
                        "if(scoreMap.get(title)!=null){" +
                        "phoneScore = (double)scoreMap.get(title);" +
                        "} " +
                        "score = phoneScore*price+_score;" +
                        "return score;";

        ScriptScoreFunctionBuilder scriptScoreFunctionBuilder = ScoreFunctionBuilders.scriptFunction(new Script(Script.DEFAULT_SCRIPT_TYPE, Script.DEFAULT_SCRIPT_LANG, scoreScript, params));
        FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(boolQueryBuilder, scriptScoreFunctionBuilder).
                scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);
        searchSourceBuilder.query(functionScoreQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("分数为:"+hit.getScore()+",数据为:" + hit.getSourceAsString());
        }
        client.close();

在这里插入图片描述

自定义打分(在搜索结果中增加权重)

1.更改了脚本分数的计算方式,增加了Math.log10()函数,让结果更加平稳
2.增加了weight()函数,使结果可以二次排序

  SearchRequest searchRequest = new SearchRequest("products");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.filter(QueryBuilders.termsQuery("brand", "vivo"));
        Map<String, Object> params = new HashMap(8);
        Map<String, Double> scoreMap = new HashMap<>(16);
        scoreMap.put("vivo手机", 2d);
        scoreMap.put("NEX手机", 1.5d);
        scoreMap.put("xplay手机", 1d);
        scoreMap.put("iQOO手机", 3d);
        params.put("scoreMap", scoreMap);

        final String scoreScript =
                "HashMap scoreMap = (HashMap)params.scoreMap;double score = 0d;" +
                        "String title = doc['title'].value;" +
                        "double price = doc['price'].value;" +
                        "double phoneScore = 0d; " +
                        "if(scoreMap.get(title)!=null){" +
                        "phoneScore = (double)scoreMap.get(title);" +
                        "} " +
                        "score = Math.log10(1d+phoneScore*price)+_score;" +
                        "return score;";

        List<FunctionScoreQueryBuilder.FilterFunctionBuilder> filterFunctionBuilderList =  new ArrayList<>();
        filterFunctionBuilderList.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("price","899.99"),
                ScoreFunctionBuilders.weightFactorFunction(10)));
        ScriptScoreFunctionBuilder scriptScoreFunctionBuilder = ScoreFunctionBuilders.scriptFunction(new Script(Script.DEFAULT_SCRIPT_TYPE, Script.DEFAULT_SCRIPT_LANG, scoreScript, params));
        FunctionScoreQueryBuilder.FilterFunctionBuilder filterFunctionBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchAllQuery(), scriptScoreFunctionBuilder);
        filterFunctionBuilderList.add(filterFunctionBuilder);
        FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = filterFunctionBuilderList.toArray(new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilderList.size()]);
        FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(boolQueryBuilder, filterFunctionBuilders).
                scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);
        searchSourceBuilder.query(functionScoreQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("分数为:"+hit.getScore()+",数据为:" + hit.getSourceAsString());
        }

DSL如下

{
  "function_score" : {
    "query" : {
      "bool" : {
        "filter" : [
          {
            "terms" : {
              "brand" : [
                "vivo"
              ],
              "boost" : 1.0
            }
          }
        ],
        "adjust_pure_negative" : true,
        "boost" : 1.0
      }
    },
    "functions" : [
      {
        "filter" : {
          "term" : {
            "price" : {
              "value" : "899.99",
              "boost" : 1.0
            }
          }
        },
        "weight" : 10.0
      },
      {
        "filter" : {
          "match_all" : {
            "boost" : 1.0
          }
        },
        "script_score" : {
          "script" : {
            "source" : "HashMap scoreMap = (HashMap)params.scoreMap;double score = 0d;String title = doc['title'].value;double price = doc['price'].value;double phoneScore = 0d; if(scoreMap.get(title)!=null){phoneScore = (double)scoreMap.get(title);} score = Math.log10(1d+phoneScore*price)+_score;return score;",
            "lang" : "painless",
            "params" : {
              "scoreMap" : {
                "iQOO手机" : 3.0,
                "NEX手机" : 1.5,
                "vivo手机" : 2.0,
                "xplay手机" : 1.0
              }
            }
          }
        }
      }
    ],
    "score_mode" : "sum",
    "boost_mode" : "sum",
    "max_boost" : 3.4028235E38,
    "boost" : 1.0
  }
}

nested 查询

在这里插入图片描述

        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("blog_new");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String nestedPath="comments";
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder nameMatch = QueryBuilders.matchQuery("comments.name", "steve");
        MatchQueryBuilder ageMatch = QueryBuilders.matchQuery("comments.age", 66);
        BoolQueryBuilder queryBuilder = boolQueryBuilder.must(nameMatch).must(ageMatch);
        NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(nestedPath, queryBuilder, ScoreMode.None);
        searchSourceBuilder.query(nestedQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchRes.getHits();
        for (SearchHit hit : hits) {
            System.out.println("数据为:" + hit.getSourceAsString());
        }

Nested 更新

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String nestedPath="comments";
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder nameMatch = QueryBuilders.matchQuery("comments.name", "steve");
        BoolQueryBuilder queryBuilder = boolQueryBuilder.must(nameMatch);
        NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(nestedPath, queryBuilder, ScoreMode.None);
        searchSourceBuilder.query(nestedQueryBuilder);
        UpdateByQueryRequest updateByQueryRequest =new UpdateByQueryRequest();
        updateByQueryRequest.indices("blog_new");
        updateByQueryRequest.setMaxRetries(3);
        String script=" for(e in ctx._source.comments){if (e.name == params.name) {e.age = params.age; e.comment= 'very very good article...';}}";
        Map<String, Object> params =new HashMap<>();
        params.put("name","steve");
        params.put("age",48);
        updateByQueryRequest.setScript(new Script(ScriptType.INLINE, "painless", script, params));
        updateByQueryRequest.setQuery(nestedQueryBuilder);
        client.updateByQuery(updateByQueryRequest,RequestOptions.DEFAULT);

通过Http向ES发送请求,测试于ES7.10版本


 public static void httpToES() throws Exception {

        try {
            RestTemplate restTemplate = new RestTemplate();

            String endpoint = "http://localhost:9200/synonym_index/_analyze";

            // 设置请求头和请求体
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

            Map<String, Object> requestMap = new HashMap<>();
            requestMap.put("analyzer", "ik_max_word");
            requestMap.put("text", "Hello World");

            // 创建 HttpEntity 对象
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestMap, headers);

            // 发送 POST 请求,并处理 Elasticsearch 返回的响应
            ResponseEntity<String> responseEntity = restTemplate.exchange(endpoint, HttpMethod.POST, requestEntity, String.class);
            String responseBody = responseEntity.getBody();

            System.out.println(responseBody);

        } catch (Exception e){
            e.printStackTrace();
        }

返回结果
在这里插入图片描述

有一些写法可以参考
https://www.kgraph.cn/218.html

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐