第八节 ElasticSearch的文档查询编程

亮子 2021-06-17 02:03:40 21909 0 0 0

1、简单配置

@Configuration
public class ElasticsearchConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1",9200,"http")));
        return client;
    }

}

2、查询条件QueryBuilder的构建方法举例

在使用聚合查询之前我们有必要先来了解下创建查询条件QueryBuilder的几种常用方法

1)、精确查询(必须完全匹配上)

//-- 单个匹配termQuery

//不分词查询 参数1: 字段名,参数2:字段查询值,因为不分词,所以汉字只能查询一个字,英语是一个单词.
QueryBuilder queryBuilder=QueryBuilders.termQuery("fieldName", "fieldlValue");

//分词查询,采用默认的分词器
QueryBuilder queryBuilder2 = QueryBuilders.matchQuery("fieldName", "fieldlValue");

//--多个匹配
//不分词查询,参数1: 字段名,参数2:多个字段查询值,因为不分词,所以汉字只能查询一个字,英语是一个单词.
QueryBuilder queryBuilder=QueryBuilders.termsQuery("fieldName", "fieldlValue1","fieldlValue2...");

//分词查询,采用默认的分词器
QueryBuilder queryBuilder= QueryBuilders.multiMatchQuery("fieldlValue", "fieldName1", "fieldName2", "fieldName3");

//匹配所有文件,相当于就没有设置查询条件
QueryBuilder queryBuilder=QueryBuilders.matchAllQuery();

2)、模糊查询(只要包含即可)

//模糊查询常见的5个方法如下
//1.常用的字符串查询
QueryBuilders.queryStringQuery("fieldValue").field("fieldName");//左右模糊

//2.常用的用于推荐相似内容的查询
QueryBuilders.moreLikeThisQuery(new String[] {"fieldName"}).addLikeText("pipeidhua");

//如果不指定filedName,则默认全部,常用在相似内容的推荐上

//3.前缀查询  如果字段没分词,就匹配整个字段前缀
QueryBuilders.prefixQuery("fieldName","fieldValue");

//4.fuzzy query:分词模糊查询,通过增加fuzziness模糊属性来查询,如能够匹配hotelName为tel前或后加一个字母的文档,fuzziness 的含义是检索的term 前后增加或减少n个单词的匹配查询
QueryBuilders.fuzzyQuery("hotelName", "tel").fuzziness(Fuzziness.ONE);

//5.wildcard query:通配符查询,支持* 任意字符串;?任意一个字符
QueryBuilders.wildcardQuery("fieldName","ctr*");//前面是fieldname,后面是带匹配字符的字符串
QueryBuilders.wildcardQuery("fieldName","c?r?");

3、条件查询

    @Test
    public void searchQuery() throws IOException {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("name", "吕"));
//        sourceBuilder.query(QueryBuilders.termQuery("age", 23));
        sourceBuilder.from(0);
        sourceBuilder.size(5);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("tb_hero");
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(searchResponse);

        RestStatus status = searchResponse.status();
        TimeValue took = searchResponse.getTook();
        Boolean terminatedEarly = searchResponse.isTerminatedEarly();
        boolean timedOut = searchResponse.isTimedOut();
        System.out.println(status);
    }

4、搜索示例代码

package com.shenmazong.serverdemoes.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticSearchClientConfig {

    @Bean
    RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("127.0.0.1", 9200, "http")
                )
        );

        return client;
    }
}
package com.shenmazong.serverdemoes;

import com.alibaba.fastjson.JSON;
import com.shenmazong.serverdemoes.pojo.TbProduct;
import com.shenmazong.serverdemoes.pojo.TbUser;
import com.shenmazong.serverdemoes.util.UtilHtmlParser;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
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.support.master.AcknowledgedResponse;
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.client.indices.GetIndexRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
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.ArrayList;
import java.util.List;
import java.util.Map;

// http://localhost:5601/app/kibana#/dev_tools/console?_g=()
// 文档
// https://www.elastic.co/guide/cn/elasticsearch/guide/current/_creating_an_index.html
// java-rest-high 文档
// https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-create-index.html
// https://github.com/elastic/elasticsearch/tree/7.6


@SpringBootTest
class ServerDemoEsApplicationTests {

    @Autowired
    RestHighLevelClient restHighLevelClient;

    /**
     * TODO 创建索引
     * @throws IOException
     */
    @Test
    void testCreateIndex() throws IOException {
        //1、创建索引请求
        CreateIndexRequest request = new CreateIndexRequest("shenmazong_index");

        //2、设置副本和分片信息
        request.settings(Settings.builder()
                .put("index.number_of_shards", 3)
                .put("index.number_of_replicas", 2)
        );

        //3、设置映射设置
        request.mapping(
                "{\n" +
                        "  \"properties\": {\n" +
                        "    \"message\": {\n" +
                        "      \"type\": \"text\"\n" +
                        "    }\n" +
                        "  }\n" +
                        "}",
                XContentType.JSON);
        //3、设置映射
//        XContentBuilder builder = XContentFactory.jsonBuilder();
//        builder.startObject();
//        {
//            builder.startObject("properties");
//            {
//                builder.startObject("message");
//                {
//                    builder.field("type", "text");
//                }
//                builder.endObject();
//            }
//            builder.endObject();
//        }
//        builder.endObject();
//        request.mapping(builder);

//        request.source("{\n" +
//                "    \"settings\" : {\n" +
//                "        \"number_of_shards\" : 1,\n" +
//                "        \"number_of_replicas\" : 0\n" +
//                "    },\n" +
//                "    \"mappings\" : {\n" +
//                "        \"properties\" : {\n" +
//                "            \"message\" : { \"type\" : \"text\" }\n" +
//                "        }\n" +
//                "    },\n" +
//                "    \"aliases\" : {\n" +
//                "        \"twitter_alias\" : {}\n" +
//                "    }\n" +
//                "}", XContentType.JSON);

        //2、客户端执行请求 IndicesClient
        CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);

        System.out.println(response);
    }

    /**
     * TODO 测试索引
     * @throws IOException
     */
    @Test
    void testExistIndex() throws IOException {
        GetIndexRequest request = new GetIndexRequest("shenmazong_index");
        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);

        System.out.println(exists);
    }

    /**
     * TODO 删除索引
     * @throws IOException
     */
    @Test
    void testDeleteIndex() throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest("shenmazong_index");
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);

        System.out.println(delete.isAcknowledged());
    }

    /**
     * TODO 测试添加文档
     */
    @Test
    void testAddDocument() throws IOException {
        // 创建对象
        TbUser user = new TbUser("田不平", 3, "暖男");

        // 创建请求
        IndexRequest request = new IndexRequest("shenmazong_index");

        // 规则 put /shen_index/_doc/1
        request.id("1");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");

        // 将我们的文档数据放入请求的 json
        request.source(JSON.toJSON(user), XContentType.JSON);

        // 客户端发送请求
        IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);

        System.out.println(indexResponse.toString());
        System.out.println(indexResponse.status());
    }

    /**
     * TODO 判断文档是否存在
     */

    @Test
    void testExistDocument() throws IOException {
        GetRequest request = new GetRequest("shenmazong_index", "1");

        // 不获取返回的 _source 上下文数据
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none_");

        boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    /**
     * TODO 获取文档信息
     */
    @Test
    void testGetDocument() throws IOException {
        GetRequest request = new GetRequest("shenmazong_index", "1");
        GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);

        // 打印字符串格式的数据
        System.out.println(response.getSourceAsString());

        // 返回全部内容,和命令字符串是一样的
        System.out.println(response);
    }

    /**
     * TODO 修改文档信息
     */

    @Test
    void testSetDocument() throws IOException {
        UpdateRequest request = new UpdateRequest("shenmazong_index", "1");

        // 设置操作超时
        request.timeout("1s");

        // 设置修改的内容
        TbUser user = new TbUser("参码踪", 18, "帅哥");
        request.doc(JSON.toJSONString(user), XContentType.JSON);

        UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }

    /**
     * TODO 删除文档信息
     */
    @Test
    void testDeleteDocument() throws IOException {
        DeleteRequest request = new DeleteRequest("shenmazong_index", "1");

        request.timeout("1s");

        DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }

    /**
     * TODO 批量增加文档信息
     */
    @Test
    void testBulkAddDocument() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");

        ArrayList<TbUser> users = new ArrayList<>();
        users.add(new TbUser("李白", 22, "诗仙"));
        users.add(new TbUser("杜甫", 13, "诗圣"));

        // 循环生成请求数据
        int i = 2;
        for(TbUser user : users) {
            bulkRequest.add(
                    new IndexRequest("shenmazong_index")
                    .id(""+i++)
                    .source(JSON.toJSONString(user), XContentType.JSON)
            );
        }

        BulkResponse response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);

        // 是否失败,返回false,表示成功
        System.out.println(response.hasFailures());
    }

    /**
     * TODO 测试查找
     */
    @Test
    void testSearch() throws IOException {

        SearchRequest request = new SearchRequest("shenmazong_index");

        SearchSourceBuilder builder = new SearchSourceBuilder();

        // 条件查询,使用QueryBuilders工具类实现
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", "22");
        //MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        builder.query(termQueryBuilder);

        builder.timeout(TimeValue.timeValueSeconds(10));

        builder.from(0);
        builder.size(10);

        request.source(builder);

        // 执行查询
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        // 打印查询字符串格式的结果
        System.out.println(JSON.toJSONString(response.getHits()));

        // 打印为map格式
        for(SearchHit hit : response.getHits().getHits()) {
            System.out.println(hit.getSourceAsMap());
        }
    }

    /**
     * TODO 测试批量数据导入
     * @throws IOException
     */
    @Test
    void testBulkAddJd() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");

        List<TbProduct> products = new UtilHtmlParser().getJdHtml("java");


        // 循环生成请求数据
        int i = 2;
        for(TbProduct product : products) {
            bulkRequest.add(
                    new IndexRequest("jd_index")
                            .id(""+i++)
                            .source(JSON.toJSONString(product), XContentType.JSON)
            );
        }

        BulkResponse response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);

        // 是否失败,返回false,表示成功
        System.out.println(response.hasFailures());
    }


    /**
     * TODO 测试高亮查找
     */
    @Test
    void testHighLightSearch() throws IOException {

        SearchRequest request = new SearchRequest("jd_index");

        SearchSourceBuilder builder = new SearchSourceBuilder();

        // 条件查询,使用QueryBuilders工具类实现
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "java");
        //MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        builder.query(termQueryBuilder);

        builder.timeout(TimeValue.timeValueSeconds(10));

        builder.from(0);
        builder.size(10);

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 只匹配标题
        highlightBuilder.field("title");
        // 只匹配第一个
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");

        builder.highlighter(highlightBuilder);


        request.source(builder);

        // 执行查询
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        // 打印查询字符串格式的结果
        System.out.println(JSON.toJSONString(response.getHits()));

        // 打印为map格式
        for(SearchHit hit : response.getHits().getHits()) {

            // 获取高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();

            // 解析高亮字段,将原来的字段替换为高亮字段
            HighlightField title = highlightFields.get("title");
            if(title != null) {
                Text[] fragments = title.fragments();
                String newTitle = "";
                for(Text text : fragments) {
                    newTitle += text;
                }

                // 高亮字段替换原来的内容
                sourceAsMap.put("title", newTitle);
            }

            //System.out.println(hit.getSourceAsMap());
            System.out.println(sourceAsMap);
        }
    }
}