ElasticSearch Java Api

2021/4/9 20:28:58

本文主要是介绍ElasticSearch Java Api,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

//2.添加配置
@Configuration //xml
public class ElasticSearchClientConfig {

    @Bean  //bean Class             //bean id
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("127.0.0.1", 9201, "http"),
                        new HttpHost("127.0.0.1", 9202, "http"),
                        new HttpHost("127.0.0.1", 9203, "http")
                ));
        return client;
    }
}

 

 

/*
    * 重建索引
    * @desc
    *  对已存在的字段进行修改和删除,修改字段的类型,字段的分词器,增加新的子字段等操作 时 都必须重建索引
    *      对当前的索引新建一个别名
            新建一个新的索引,同步结构
            同步数据
            给新的索引见一个别名
            删除老的索引的别名
            删除老的索引
    * 1、新建一个index
    * 2、定制mappings
    * 3、数据迁移scroll 、 批量操作bulk
    * 4、索引使用别名,无需重启机器,不影响逻辑
    *
    *
    * */

    @Test
    void deleteIndex() throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(new String[]{"my_index"});//删除不能使用别名
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        log.info("删除索引是否成功 {}", response.isAcknowledged());
    }

    /*

{
   "properties": {
      "id": {
         "type": "long"
      },

      "name": {
         "analyzer": "analysis-ik",
         "type": "text"
      },
      "sex": {
         "type": "text"
      },
      "age": {
         "type": "long"
      },
      "birthday": {
         "type": "date"
      },
      "desc": {
         "analyzer": "analysis-ik",
         "type": "text"
      },
      "salary": {
         "type": "long"
      }
   }
}


     */
    @Test
    void createIndex() throws IOException {
        CreateIndexRequest user_index = new CreateIndexRequest("user_index");
        String mapping = "{\"properties\":{\"id\":{\"type\":\"text\"},\"name\":{\"analyzer\":\"analysis-ik\",\"type\":\"text\"},\"sex\":{\"type\":\"text\"},\"age\":{\"type\":\"long\"},\"birthday\":{\"type\":\"date\",\"format\":\"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis\"},\"desc\":{\"analyzer\":\"analysis-ik\",\"type\":\"text\"},\"salary\":{\"type\":\"long\"}}}";

        user_index.mapping("_doc", mapping, XContentType.JSON);
        //创建别名
        Alias alias = new Alias("user");
        user_index.alias(alias);
        //执行创建请求,获得相应
        CreateIndexResponse response = client.indices().create(user_index, RequestOptions.DEFAULT);
        log.info("创建完毕 {}", response);
    }

    @Test
    void getIndex() throws IOException {
        GetIndexRequest request = new GetIndexRequest("user"); //别名也可以
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        log.info("判断索引是否存在 {}", exists);
    }


    @Test
    void addDocument() throws IOException {
        HashMap<Object, Object> result = new HashMap<>();
        result.put("id", UUID.randomUUID().toString().replace("-", ""));
        result.put("name", "李白");
        result.put("age", 31);
        result.put("sex", "男");
        result.put("desc", "其中8例确诊病例和1例无症状感染者为瑞丽市第二轮全员核酸检测中发现,即用负压救护车转运至定点医疗机构,结合流行病学史、临床表现和实验室检测结果,诊断为新冠肺炎和无症状感染者。其余3例确诊病例为在院隔离观察的无症状感染者转为确诊病例。流调工作仍在紧张进行中。");
        result.put("birthday", "1990-11-02 12:22:11");
        result.put("salary", 17500);

        //创建请求
        IndexRequest request = new IndexRequest("testdoct");
        //规则 /user_index/_doc/1
        request.id("1");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //放入json
        IndexRequest source = request.source(JSON.toJSONString(result), XContentType.JSON);
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);

        //打印相应结果
        log.info("创建文档{}", response.status());//create
    }


    //3.查询所有的记录
    @Test
    public void testAllIndex() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");

        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        sourceBuilder.query(
                //指定查询条件
                QueryBuilders
                        .matchAllQuery()) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                .postFilter(QueryBuilders.matchAllQuery())//过滤条件
                .sort("age", SortOrder.DESC) //排序
                .highlighter(new HighlightBuilder().field("*").requireFieldMatch(false));//高亮
        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsMap());
        }
    }


    @Test
    void getDocument() throws IOException {
        GetRequest request = new GetRequest("user_index", "1");
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        log.info("判断是否存在{}", exists);

        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        log.info("{}", response.getSourceAsString());
    }

    @Test
    void getDocumentByDesc() throws IOException {
        SearchRequest request = new SearchRequest("testdoct");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        QueryBuilder queryBuilder = QueryBuilders.matchQuery("desc", "瑞丽");

        sourceBuilder.query(queryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        request.source(sourceBuilder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        log.info("查询是否成功 {} ", response.status());
        log.info("查询结果 {} ", response);
    }

    @Test
    void updateDocument() throws IOException {
        UpdateRequest request = new UpdateRequest("user", "1");
        request.timeout(TimeValue.timeValueSeconds(1));

        HashMap<Object, Object> result = new HashMap<>();
        result.put("id", UUID.randomUUID().toString().replace("-", ""));
        result.put("name", "张三丰");

        request.doc(JSON.toJSONString(result), XContentType.JSON);

        UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
        log.info("查看是否修改成功 {}", response.status());
    }


    @Test
    void deleteDocument() throws IOException {
        DeleteRequest request = new DeleteRequest("user_index", "2");
        request.timeout(TimeValue.timeValueSeconds(1));

        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        log.info("查看是否删除成功 {}", response.status());
    }

    @Test
    void bulkAdd() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");

        ArrayList<HashMap<Object, Object>> userDemos = new ArrayList<>();

        HashMap<Object, Object> user1 = new HashMap<>();
        user1.put("id", UUID.randomUUID().toString().replace("-", ""));
        user1.put("name", "电光马子");
        user1.put("age", 51);
        user1.put("sex", "男");
        user1.put("desc", "经查,德宏州瑞丽市在半年多时间内,连续3次发生新冠肺炎疫情事件,特别是“3·29”疫情事件,严重冲击和破坏了全国、全省疫情防控大局,严重冲击和影响了全省经济社会发展和工作大局,造成严重后果和恶劣影响。龚云尊同志作为时任瑞丽市委书记,负有主要领导责任。经省委研究同意,给予龚云尊同志撤销党内职务、政务撤职处分,降为一级调研员。(完)");
        user1.put("birthday", "1970-11-02 15:26:11");
        user1.put("salary", 3500);

        userDemos.add(user1);

        HashMap<Object, Object> user2 = new HashMap<>();
        user2.put("id", UUID.randomUUID().toString().replace("-", ""));
        user2.put("name", "司空镇");
        user2.put("age", 99);
        user2.put("sex", "男");
        user2.put("desc", "当地时间7日,世卫组织发布阿斯利康新冠疫苗安全性临时声明,声明指出,世卫组织全球疫苗安全咨询委员会新冠肺炎小组委员会已评估了接种阿斯利康新冠疫苗后出现血栓和血小板减少的报告,于4月7日召开了最新一次会议。委员会还评估了欧洲药品管理局,以及英国药品和保健品监管局提供的最新信息,认为阿斯利康疫苗与血栓和血小板减少存在可能的因果关系,但尚未证实,还需专门研究以充分了解其中的潜在关系,世卫组织全球疫苗安全咨询委员会正在搜集和评估更多数据。");
        user2.put("birthday", "1922-11-02 09:45:11");
        user2.put("salary", 1000);
        userDemos.add(user2);


        for (int i = 0; i < userDemos.size(); i++) {
            IndexRequest indexRequest = new IndexRequest("testdoct");
            int tempId = i + 2;
            indexRequest.id("" + tempId); //不设置都是随机id自动设置,不是指文档字段的id 而是es自己维护的id
            indexRequest.source(JSON.toJSONString(userDemos.get(i)), XContentType.JSON);
            bulkRequest.add(indexRequest);
        }

        BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        log.info("批量插入是否成功{}", !response.hasFailures());//hasFailures本意返回false是没有失败

    }


    @Test
    void highLightSearch() throws IOException {
        SearchRequest request = new SearchRequest("testdoct");
        //构建搜索的条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "司");
        sourceBuilder.query(queryBuilder);


        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.preTags("<p color='red'>");
        highlightBuilder.postTags("</p>");
        highlightBuilder.requireFieldMatch(false);//不需要多个高亮
        sourceBuilder.highlighter(highlightBuilder);


        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        request.source(sourceBuilder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        log.info("查询是否成功 {} ", response.status());
        log.info("查询结果 {} ", response);

        for (SearchHit hit : response.getHits().getHits()) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("desc");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("desc ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }

        SearchHits hits = response.getHits();
        log.info("最终 {}", hits);
    }

    @Test
    void paged() throws IOException {
        SearchRequest request = new SearchRequest("testdoct");
        //构建搜索的条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        QueryBuilder queryBuilder = QueryBuilders.matchQuery("desc", "在");
        sourceBuilder.query(queryBuilder);


        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("desc");
        highlightBuilder.preTags("<p color='red'>");
        highlightBuilder.postTags("</p>");
        highlightBuilder.requireFieldMatch(false);//不需要多个高亮
        sourceBuilder.highlighter(highlightBuilder);


        //分页
        sourceBuilder.from(2);
        sourceBuilder.size(1);

        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        request.source(sourceBuilder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        log.info("查询是否成功 {} ", response.status());
        log.info("查询结果 {} ", response);

        for (SearchHit hit : response.getHits().getHits()) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("desc");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("desc ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }

        SearchHits hits = response.getHits();
        log.info("最终 {}", hits);
    }

    //滚动查询
    @Test
    void scrollReq() {
        ArrayList<String> list = new ArrayList<>();
        //设定滚动时间间隔,60秒,不是处理查询结果的所有文档的所需时间
        //游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了
        final Scroll scroll = new Scroll(TimeValue.timeValueSeconds(60));
        SearchRequest searchRequest = new SearchRequest("testdoct");
        searchRequest.scroll(scroll);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        QueryBuilder queryBuilder = QueryBuilders
                //.boolQuery()
                //查询条件在 两个日期范围
                //.must(QueryBuilders.rangeQuery("intercept_time").gte(lastTime).lte(nowTime));
                //.matchQuery("name", "白");
                .matchAllQuery();


        //每个批次实际返回的数量
        searchSourceBuilder.query(queryBuilder);
        searchSourceBuilder.size(1);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try {
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("获取数据错误1 ->", e);
        }
        assert searchResponse != null;
        String scrollId;
        int i = 0;
        do {
            for (SearchHit hit : searchResponse.getHits().getHits()) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                //获取需要数据
                i += 1;
                log.info("scroll 次数 {}", i);
                list.add(String.valueOf(sourceAsMap.get("name")));
            }
            //每次循环完后取得scrollId,用于记录下次将从这个游标开始取数
            scrollId = searchResponse.getScrollId();
            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
            scrollRequest.scroll(scroll);
            try {
                //进行下次查询
                searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                log.error("获取数据错误2 ->", e);
            }
        } while (searchResponse.getHits().getHits().length != 0);
        //清除滚屏
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        //也可以选择setScrollIds()将多个scrollId一起使用
        clearScrollRequest.addScrollId(scrollId);
        ClearScrollResponse clearScrollResponse = null;
        try {
            clearScrollResponse = client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.warn("清除滚屏错误 ->", e);
        }
        boolean succeeded = false;
        if (clearScrollResponse != null) {
            succeeded = clearScrollResponse.isSucceeded();
        }

    }

    //match 查询
    @Test
    void matchQuery() throws IOException {
        SearchRequest request = new SearchRequest("testdoct");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        QueryBuilder queryBuilder = QueryBuilders.matchQuery("desc", "瑞丽");

        sourceBuilder.query(queryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        request.source(sourceBuilder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        log.info("查询是否成功 {} ", response.status());
        log.info("查询结果 {} ", response);

    }

    //match 过滤
    @Test
    void matchFilter() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");

        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        sourceBuilder.query(
                //指定查询条件
                QueryBuilders
                        .matchAllQuery()) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                .postFilter(QueryBuilders.matchQuery("name", "白"))//过滤条件
                .sort("age", SortOrder.DESC) //排序
                .highlighter(new HighlightBuilder().field("*").requireFieldMatch(false));//高亮
        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsMap());
        }

    }

    //term 过滤
    @Test
    void termFilter() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");

        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        sourceBuilder.query(
                //指定查询条件
                QueryBuilders
                        .matchAllQuery()) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                .postFilter(QueryBuilders.termQuery("name", "白"))//过滤条件
                .sort("age", SortOrder.DESC) //排序
                .highlighter(new HighlightBuilder().field("*").requireFieldMatch(false));//高亮
        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsMap());
        }
    }

    //bool查询
    @Test
    void boolQuery() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");
        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                //指定查询条件
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.rangeQuery("age").from("10").to("35"))
                //.should(QueryBuilders.rangeQuery("age").from("36").to(55))
        ) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                //.postFilter(QueryBuilders.matchQuery("name", "白"))//过滤条件
                .sort("age", SortOrder.DESC)//排序
                .highlighter(new HighlightBuilder()
                        .field("name")
                        .preTags("<p color='red'>")
                        .postTags("</p>")
                        .requireFieldMatch(false));
        ;//高亮 只能针对term match

        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        log.info(JSON.toJSONString(JSON.toJSONString(search)));
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("name");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("name ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }
    }

    //bool过滤
    @Test
    void boolFilter() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");
        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                //指定查询条件
                QueryBuilders.matchAllQuery()
        ) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                .postFilter(QueryBuilders.boolQuery()
                        .must(QueryBuilders.rangeQuery("age").from(10).to(35))
                )//过滤条件
                .sort("age", SortOrder.DESC)//排序
                .highlighter(new HighlightBuilder()
                        .field("name")
                        .preTags("<p color='red'>")
                        .postTags("</p>")
                        .requireFieldMatch(false));//高亮 只能针对term match

        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        log.info(JSON.toJSONString(JSON.toJSONString(search)));
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("name");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("name ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }

    }

    //range查询
    @Test
    void rangeQuery() throws IOException {
        SearchRequest request = new SearchRequest("testdoct");
        //构建搜索的条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        //区间查询
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").from("30").to("55");

        sourceBuilder.query(rangeQueryBuilder);


        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.preTags("<p color='red'>");
        highlightBuilder.postTags("</p>");
        highlightBuilder.requireFieldMatch(false);//不需要多个高亮
        sourceBuilder.highlighter(highlightBuilder);


        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        request.source(sourceBuilder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        log.info("查询是否成功 {}", response.status());

        for (SearchHit hit : response.getHits().getHits()) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("name");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("name ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }

        SearchHits hits = response.getHits();
    }

    //range过滤
    @Test
    void rangeFilter() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");
        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                //指定查询条件
                QueryBuilders.matchAllQuery()
        ) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                .postFilter(QueryBuilders.rangeQuery("age").from(10).to(35)
                )//过滤条件
                .sort("age", SortOrder.DESC)//排序
                .highlighter(new HighlightBuilder()
                        .field("name")
                        .preTags("<p color='red'>")
                        .postTags("</p>")
                        .requireFieldMatch(false));//高亮 只能针对term match

        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        log.info(JSON.toJSONString(JSON.toJSONString(search)));
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("name");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("name ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }
    }

    //prefix查询
    @Test
    void prefixQuery() throws IOException {
        SearchRequest request = new SearchRequest("testdoct");
        //构建搜索的条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        //PrefixQueryBuilder prefixQueryBuilder = new PrefixQueryBuilder("name", "李");
        PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery("name", "李");
        sourceBuilder.query(prefixQueryBuilder);

        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.preTags("<p color='red'>");
        highlightBuilder.postTags("</p>");
        highlightBuilder.requireFieldMatch(false);//不需要多个高亮
        sourceBuilder.highlighter(highlightBuilder);


        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        request.source(sourceBuilder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        log.info("查询是否成功 {}", response.status());

        for (SearchHit hit : response.getHits().getHits()) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("name");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("name ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }

        SearchHits hits = response.getHits();
    }

    //prefix过滤
    @Test
    void prefixFilter() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");
        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                //指定查询条件
                QueryBuilders.matchAllQuery()
        ) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                .postFilter(QueryBuilders.prefixQuery("name", "李")
                )//过滤条件
                .sort("age", SortOrder.DESC)//排序
                .highlighter(new HighlightBuilder()
                        .field("name")
                        .preTags("<p color='red'>")
                        .postTags("</p>")
                        .requireFieldMatch(false));//高亮 只能针对term match

        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        log.info(JSON.toJSONString(JSON.toJSONString(search)));
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("name");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("name ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }
    }

    //wildcard查询  用于模糊通配查询 但是要注意是否是keyword,如果不是keyword可能被分词,导致查询失败
    //? 代表一个字符  * 代表多个字符
    /*
    GET booke/member/_search
{"query": {
    "wildcard":{
      "senderName": "李*"
    }
}


     */
    @Test
    void wildcardQuery() throws IOException {
            //boolQueryBuilder.should(QueryBuilders.wildcardQuery("word.keyword", "*" + obj + "*"));
            //boolQueryBuilder.should(QueryBuilders.wildcardQuery("word", "*" + obj + "*"));
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(
                QueryBuilders.boolQuery().
                        //should(QueryBuilders.wildcardQuery("name", "*" + "空" + "*"))
                        should(QueryBuilders.wildcardQuery("name", "*" + "白"))
        );

        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        SearchHit[] hits = searchResponse.getHits().getHits();
        log.info("{}",hits);
    }

    //exists 过滤器
    @Test
    void existsFilter() throws IOException {
        //参数1:索引  参数2:类型  参数3:id
        SearchRequest searchRequest = new SearchRequest("testdoct");
        //构建搜索对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                //指定查询条件
                QueryBuilders.matchAllQuery()
        ) //所有记录数
                .from(0)//起始条数
                .size(20) //每页记录数
                .postFilter(QueryBuilders.existsQuery("name")
                )//过滤条件
                .sort("age", SortOrder.DESC)//排序
                .highlighter(new HighlightBuilder()
                        .field("name")
                        .preTags("<p color='red'>")
                        .postTags("</p>")
                        .requireFieldMatch(false));//高亮 只能针对term match

        //创建搜索请求
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档数:" + search.getHits().getTotalHits());
        System.out.println("最大得分:" + search.getHits().getMaxScore());
        log.info(JSON.toJSONString(JSON.toJSONString(search)));
        //所有记录数
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("name");

            if (title != null) {
                Text[] fragments = title.getFragments();
                String highTitle = "";

                for (Text fragment : fragments) {
                    highTitle += fragment;
                }

                sourceAsMap.put("name ", highTitle);//内容替换
            }
            log.info(JSON.toJSONString(hit.getSourceAsMap()));
        }
    }



    //分析词语

    //Metric 聚集查询整体信息
    @Test
    void metricStat() throws IOException {
        String responseResult = "";
        try {
            // 设置聚合条件
            AggregationBuilder aggr = AggregationBuilders.stats("age_stats").field("age");
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.aggregation(aggr);
            // 设置查询结果不返回,只返回聚合结果
            searchSourceBuilder.size(0);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status()) || aggregations != null) {
                // 转换为 Stats 对象
                ParsedStats aggregation = aggregations.get("age_stats");
                //ParsedMax
                //ParsedMin
                //ParsedAvg
                //ParsedPercentiles
                //ParsedValueCount

                log.info("-------------------------------------------");
                log.info("聚合信息:");
                log.info("count:{}", aggregation.getCount());
                log.info("avg:{}", aggregation.getAvg());
                log.info("max:{}", aggregation.getMax());
                log.info("min:{}", aggregation.getMin());
                log.info("sum:{}", aggregation.getSum());
                log.info("-------------------------------------------");
            }
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
            responseResult = response.toString();
        } catch (IOException e) {
            log.error("", e);
        }
        //return responseResult
    }

    //Metric 聚集查询  总数
    @Test
    void metricCount() {
        String responseResult = "";
        try {
            // 设置聚合条件
            AggregationBuilder aggr = AggregationBuilders.count("age_count").field("age");
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.aggregation(aggr);
            searchSourceBuilder.size(0);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status()) || aggregations != null) {
                // 转换为 Min 对象
                ValueCount aggregation = aggregations.get("age_count");
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                log.info("count:{}", aggregation.getValue());
                log.info("-------------------------------------------");
            }
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
            responseResult = response.toString();
        } catch (IOException e) {
            log.error("", e);
        }
        //return responseResult;
    }


    //Metric 聚集查询 最高值
    @Test
    void metricMax() {
        String responseResult = "";
        try {
            // 设置聚合条件
            AggregationBuilder aggr = AggregationBuilders.max("age_max").field("age");
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.aggregation(aggr);
            searchSourceBuilder.size(0);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status()) || aggregations != null) {
                // 转换为 Min 对象
                ParsedMax aggregation = aggregations.get("age_max");
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                log.info("max:{}", aggregation.getValue());
                log.info("-------------------------------------------");
            }
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
            responseResult = response.toString();
        } catch (IOException e) {
            log.error("", e);
        }
        //return responseResult;
    }

    //Metric 聚集查询 最低值
    @Test
    void metricMin() {
        String responseResult = "";
        try {
            // 设置聚合条件
            AggregationBuilder aggr = AggregationBuilders.min("age_min").field("age");
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.aggregation(aggr);
            searchSourceBuilder.size(0);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status()) || aggregations != null) {
                // 转换为 Min 对象
                ParsedMin aggregation = aggregations.get("age_min");
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                log.info("min:{}", aggregation.getValue());
                log.info("-------------------------------------------");
            }
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
            responseResult = response.toString();
        } catch (IOException e) {
            log.error("", e);
        }
        //return responseResult;
    }

    //Metric 聚集查询 平均值
    @Test
    void metricAvg() {
        String responseResult = "";
        try {
            // 设置聚合条件
            AggregationBuilder aggr = AggregationBuilders.avg("age_avg").field("age");
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.aggregation(aggr);
            searchSourceBuilder.size(0);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status()) || aggregations != null) {
                // 转换为 Min 对象
                ParsedAvg aggregation = aggregations.get("age_avg");
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                log.info("avg:{}", aggregation.getValue());
                log.info("-------------------------------------------");
            }
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
            responseResult = response.toString();
        } catch (IOException e) {
            log.error("", e);
        }
        //return responseResult;
    }

    //Metric 聚集查询 总和
    @Test
    void metricSum() {
        String responseResult = "";
        try {
            // 设置聚合条件
            AggregationBuilder aggr = AggregationBuilders.sum("age_sum").field("age");
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.aggregation(aggr);
            searchSourceBuilder.size(0);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status()) || aggregations != null) {
                // 转换为 Min 对象
                ParsedSum aggregation = aggregations.get("age_sum");
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                log.info("sum:{}", aggregation.getValue());
                log.info("-------------------------------------------");
            }
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
            responseResult = response.toString();
        } catch (IOException e) {
            log.error("", e);
        }
        //return responseResult;
    }

    //Bucket聚合 term
    @Test
    void bucketTerm() {
        try {
            AggregationBuilder aggr = AggregationBuilders.terms("age_bucket").field("age");
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.size(10);
            searchSourceBuilder.aggregation(aggr);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status())) {
                // 分桶
                Terms byCompanyAggregation = aggregations.get("age_bucket");
                List<? extends Terms.Bucket> buckets = byCompanyAggregation.getBuckets();
                // 输出各个桶的内容
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                for (Terms.Bucket bucket : buckets) {
                    log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
                }
                log.info("-------------------------------------------");
            }
        } catch (IOException e) {
            log.error("", e);
        }
    }

    //Bucket聚合 range
    @Test
    void bucketRange() {
        try {
            AggregationBuilder aggr = AggregationBuilders.range("age_range_bucket")
                    .field("age")
                    .addUnboundedTo("儿童", 50)
                    .addRange("中年", 50, 90)
                    .addRange("高中年", 90, 100)
                    .addUnboundedFrom("老年", 100);
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.size(0);
            searchSourceBuilder.aggregation(aggr);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status())) {
                // 分桶
                Range byCompanyAggregation = aggregations.get("age_range_bucket");
                List<? extends Range.Bucket> buckets = byCompanyAggregation.getBuckets();
                // 输出各个桶的内容
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                for (Range.Bucket bucket : buckets) {
                    log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
                }
                log.info("-------------------------------------------");
            }
        } catch (IOException e) {
            log.error("", e);
        }
    }

    //Bucket聚合 histogram
    @Test
    void bucketHistogram() {
        try {
            AggregationBuilder aggr = AggregationBuilders.histogram("salary_histogram")
                    .field("salary")
                    .extendedBounds(0, 30000)
                    .interval(1000);
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.size(0);
            searchSourceBuilder.aggregation(aggr);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status())) {
                // 分桶
                Histogram byCompanyAggregation = aggregations.get("salary_histogram");
                List<? extends Histogram.Bucket> buckets = byCompanyAggregation.getBuckets();
                // 输出各个桶的内容
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                for (Histogram.Bucket bucket : buckets) {
                    log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
                }
                log.info("-------------------------------------------");
            }
        } catch (IOException e) {
            log.error("", e);
        }
    }

    //嵌套聚集  按岁数分桶、然后统计每个员工工资最高值
    @Test
    void bukcketNested() throws IOException {
        try {
            AggregationBuilder testTop = AggregationBuilders.topHits("salary_max_user")
                    .size(1)
                    .sort("salary", SortOrder.DESC);

            AggregationBuilder salaryBucket = AggregationBuilders.terms("salary_bucket")
                    .field("age")
                    .size(10);

            salaryBucket.subAggregation(testTop);

            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.size(0);
            searchSourceBuilder.aggregation(salaryBucket);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("testdoct");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status())) {
                // 分桶
                Terms byCompanyAggregation = aggregations.get("salary_bucket");
                List<? extends Terms.Bucket> buckets = byCompanyAggregation.getBuckets();
                // 输出各个桶的内容
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                for (Terms.Bucket bucket : buckets) {
                    log.info("桶名:{}", bucket.getKeyAsString());
                    ParsedTopHits topHits = bucket.getAggregations().get("salary_max_user");
                    for (SearchHit hit : topHits.getHits()) {
                        log.info(hit.getSourceAsString());
                    }
                }
                log.info("-------------------------------------------");
            }
        } catch (
                IOException e) {
            log.error("", e);
        }

    }


    //对象嵌套类型
    //===START===============================

    /*
    嵌套索引中的最大字段数默认为50个,
    索引具有100个嵌套字段的1个文档实际上索引101个文档,
    因为每个嵌套文档都被索引为一个单独的隐藏文档。
    在索引中定义太多字段的情况可能导致映射爆炸

    {
   "properties": {
      "userName": {
         "type": "text"
      },
      "sex": {
         "type": "keyword"
      },
      "age": {
         "type": "long"
      },
      "phones": {
         "type": "nested",
         "properties": {
            "phone": {
               "type": "keyword"
            },
            "addr": {
               "type": "text"
            }
         }
      }
   }
}
     */
    @Test
    void createNestedIndex() throws IOException {
        CreateIndexRequest user_index = new CreateIndexRequest("user_info");
        String mapping = "{\\\"properties\\\":{\\\"userName\\\":{\\\"type\\\":\\\"text\\\"},\\\"sex\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"age\\\":{\\\"type\\\":\\\"long\\\"},\\\"phones\\\":{\\\"type\\\":\\\"nested\\\",\\\"properties\\\":{\\\"phone\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"addr\\\":{\\\"type\\\":\\\"text\\\"}}}}}";

        user_index.mapping("_doc", mapping, XContentType.JSON);
        //创建别名
        Alias alias = new Alias("userinfo");
        user_index.alias(alias);
        //执行创建请求,获得相应
        CreateIndexResponse response = client.indices().create(user_index, RequestOptions.DEFAULT);
        log.info("创建完毕 {}", response);
    }

    @Test
    void addNestedDocument() throws IOException {
        String param = "{\"userName\":\"张三\",\"sex\":\"男\",\"age\":20,\"phones\":[{\"phone\":\"19986262233\",\"addr\":\"湖北黄冈\"},{\"phone\":\"17762554531\",\"addr\":\"湖北武汉\"}]}";
        String param2 = "{\"userName\":\"李四\",\"sex\":\"女\",\"age\":20,\"phones\":[{\"phone\":\"19975262233\",\"addr\":\"湖北宜昌\"},{\"phone\":\"17762556931\",\"addr\":\"深圳南山\"}]}";
        //创建请求
        IndexRequest request = new IndexRequest("userinfo");
        //规则 /user_index/_doc/1
        //request.id("1");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //放入json
        IndexRequest source = request.source(param2, XContentType.JSON);
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);

        //打印相应结果
        log.info("创建文档{}", response.status());//create
    }

    @Test
    void nested() throws IOException {
        //创建SearchRequest对象
        SearchRequest request = new SearchRequest("userinfo");
        //创建复合查询对象
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //封装查询条件
        boolQuery.must(QueryBuilders.matchQuery("phones.phone", "19975262233"));
        boolQuery.must(QueryBuilders.matchQuery("phones.addr", "湖北宜昌"));
        //创建嵌套查询对象
        NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("phones", boolQuery, ScoreMode.None);
        //创建并设置SearchSourceBuilder对象
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(nestedQueryBuilder);
        // 将条件放入request中
        request.source(builder);
        //执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit);
        }
    }
    //===END===============================


    //父子关系
    //===START===============================
    /*
    {
   "properties": {
      "my_id": {
         "type": "keyword"
      },
      "my_join_field": {  //父子文档关系的名字
         "type": "join",  //join关键字表示这是一个父子文档关系
         "relations": {  //relations里面表示question是父,answer是子
            "question": "answer"
         }
      }
   }
}
     */
    @Test
    void createJoinIndex() throws IOException {
        CreateIndexRequest user_index = new CreateIndexRequest("my_index");
        String mapping = "{\"properties\":{\"my_id\":{\"type\":\"keyword\"},\"my_join_field\":{\"type\":\"join\",\"relations\":{\"question\":\"answer\"}}}}";

        user_index.mapping("_doc", mapping, XContentType.JSON);
        //创建别名
        Alias alias = new Alias("myindex");
        user_index.alias(alias);
        //执行创建请求,获得相应
        CreateIndexResponse response = client.indices().create(user_index, RequestOptions.DEFAULT);
        log.info("创建完毕 {}", response);
    }

    @Test
    void addJoinParentDocument() throws IOException {
        //"name": "question"表示插入的是父文档。  PUT my_index/_doc/2
        String param="{\"my_id\":\"1\",\"text\":\"This is a question\",\"my_join_field\":{\"name\":\"question\"}}";
        String param2="{\"my_id\":\"2\",\"text\":\"This is another question\",\"my_join_field\":{\"name\":\"question\"}}";
        //创建请求
        IndexRequest request = new IndexRequest("myindex");
        //规则 /user_index/_doc/1
        request.id("2");//重点!!!! 和my_id一致 否则查询失败
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //放入json
        IndexRequest source = request.source(param2, XContentType.JSON);
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);

        //打印相应结果
        log.info("创建文档{}", response.status());//create
    }


    /*
    //文档id我们可以判断子文档都是独立的文档(跟nested不一样)
    PUT my_index/_doc/4?routing=1    //routing关键字指明了路由的id是父文档1, 这个id和下面的parent关键字对应的id是一致的
{                                 //索引子文档的时候,routing是必须的,因为要确保子文档和父文档在同一个分片上。
  "my_id": "4",
  "text": "This is another answer",
  "my_join_field": {
    "name": "answer",   //name关键字指明了这是一个子文档。
    "parent": "1"
  }
}

     */

    @Test
    void addJoinChildDocument() throws IOException {
        String param="{\"my_id\":\"3\",\"text\":\"This is an answer\",\"my_join_field\":{\"name\":\"answer\",\"parent\":\"1\"}}";
        String param2="{\"my_id\":\"4\",\"text\":\"This is another answer\",\"my_join_field\":{\"name\":\"answer\",\"parent\":\"1\"}}";
        //创建请求
        IndexRequest request = new IndexRequest("myindex");
        //规则 /user_index/_doc/3?routing=1
        request.id("4");//重点!!!! 和my_id一致 否则查询失败
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        request.routing("1");
        //放入json
        IndexRequest source = request.source(param2, XContentType.JSON);
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);

        //打印相应结果
        log.info("创建文档{}", response.status());//create
    }


    /*

返回父文档
    {
  "query": {
    "has_child": {
      "type": "answer",
      "query" : {
                "match": {
                    "text" : "answer"
                }
            }
    }
  }
}


返回子文档
{
  "query": {
    "has_parent": {
      "parent_type": "question",
      "query" : {
                "match": {
                    "text" : "question"
                }
            }
    }
  }
}


查询子文档
{
  "query": {
    "parent_id": {
      "type": "answer",
      "id": "1"
    }
  }
}

使用父子文档的模式有一些需要特别关注的点:

每一个索引只能定义一个 join field
父子文档必须在同一个分片上,意味着查询,更新操作都需要加上routing
可以向一个已经存在的join field上新增关系
总的来说,嵌套对象通过冗余数据来提高查询性能,适用于读多写少的场景。父子文档类似关系型数据库中的关联关系,适用于写多的场景,减少了文档修改的范围

     */

    @Test
    public void getParent() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("my_index");
        HasChildQueryBuilder qb = JoinQueryBuilders.hasChildQuery(
                "answer",                         //要查询的子类型
                QueryBuilders.matchQuery("text","answer"),//子级属性匹配
                ScoreMode.None
        ).innerHit(new InnerHitBuilder());
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(qb);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        log.info("响应返回 :{}", response + "");
        response.getHits().forEach(message -> {
            System.out.println(message.getSourceAsString());
        });
    }

    @Test
    void getChild() throws IOException {
        SearchRequest request = new SearchRequest("myindex");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        request.source(builder);
        // 父文档名
        String parent_type = "question";
        // 子文档查询条件
        QueryBuilder matchQuery = QueryBuilders.matchQuery("text", "question"); //父级属性匹配
        // 是否计算评分
        boolean score = true;
        HasParentQueryBuilder hasParentQueryBuilder = new HasParentQueryBuilder(parent_type, matchQuery, score);
        builder.query(hasParentQueryBuilder);
        builder.from(0);
        builder.size(10);
        // 按评分排序
        builder.sort("_score");

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        log.info("响应返回 :{}", response + "");
        response.getHits().forEach(message -> {
            System.out.println(message.getSourceAsString());
        });

    }
    //===END=================================


    //优化之 合并请求
    @Test
    void mgetReq() throws IOException {
        MultiGetRequest request = new MultiGetRequest();
        request.add("myindex", "_doc", "1");
        request.add("myindex", "_doc", "2");
        request.add("myindex", "_doc", "3");
        request.add("myindex", "_doc", "4");
        MultiGetResponse result = client.mget(request, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(request));

        for(MultiGetItemResponse r:result.getResponses()){
            log.info("是否失败{}   响应结果  {}",r.isFailed(),r.getResponse().getSourceAsString());
        }
    }


}


这篇关于ElasticSearch Java Api的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程