ElasticSearch: 使用Java Api 操作 ES

对索引库作: 增、删、改

与之对应的DSL语句

Insert

创建索引库 (没有建立映射)

创建指定名称的索引库

@Test
public void createIndexTest() throws Exception {
    // 若是对索引库的增删改 都需要创建indicesClient对象, 这个就是一个操作数据库的客户端对象
    IndicesClient indicesObject = highLevelClient.indices();
    // 新建索引库创建请求: 创建一个索引库, 并指定名称
    CreateIndexRequest createIndexRequest = new CreateIndexRequest("hotel");
    // 发出索引库创建请求, 并接收索引库创建请求的响应
    CreateIndexResponse createIndexResponse = indicesObject.create(createIndexRequest, RequestOptions.DEFAULT);
    // 是否创建成功
    log.info("\n索引库是否创建成功: {}", createIndexResponse.isAcknowledged());
    log.info("\n响应结果: {}", createIndexResponse);
}

创建索引库, 并创建映射

在索引库存在时, 创建映射会失败, 原因: 索引库已存在

// 给指定索引库创建映射树
@Test
public void createMappingTest() throws Exception {
    // 获取索引库增删改操作对象
    IndicesClient indicesObject = highLevelClient.indices();
    // 新建索引库创建请求: 创建一个指定名称的索引库, 并创建映射树
    CreateIndexRequest createIndexRequest = new CreateIndexRequest("hotel");
    // 新建映射树
    createIndexRequest.mapping(
            "{\n" +
            "    \"properties\": {\n" +
            "      \"id\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"name\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_smart\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"address\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_smart\"\n" +
            "      },\n" +
            "      \"price\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"score\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"brand\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_smart\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"city\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"starName\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"business\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"location\": {\n" +
            "        \"type\": \"geo_point\"\n" +
            "      },\n" +
            "      \"pic\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      }, \n" +
            "      \"isAD\": {\n" +
            "        \"type\": \"boolean\"\n" +
            "      },\n" +
            "      \"all\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_smart\"\n" +
            "      }\n" +
            "    }\n" +
            "  }", XContentType.JSON);
	/* 上下两种创建索引方式二选一
	// 新建映射树
    createIndexRequest.source(
            "{\n" +
                "  \"mappings\": {\n" +
                "    \"properties\": {\n" +
                "      \"id\": {\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": true\n" +
                "      },\n" +
                "      \"name\": {\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"ik_max_word\",\n" +
                "        \"index\": true,\n" +
                "        \"copy_to\": \"all\"\n" +
                "      },\n" +
                "      \"address\": {\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": true\n" +
                "      },\n" +
                "      \"price\": {\n" +
                "        \"type\": \"integer\",\n" +
                "        \"copy_to\": \"all\",\n" +
                "        \"index\": true\n" +
                "      },\n" +
                "      \"score\": {\n" +
                "        \"type\": \"integer\",\n" +
                "        \"index\": true\n" +
                "      },\n" +
                "      \"brand\": {\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": true,\n" +
                "        \"copy_to\": \"all\"\n" +
                "      },\n" +
                "      \"city\": {\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": false\n" +
                "      },\n" +
                "      \"starName\": {\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": true,\n" +
                "        \"copy_to\": \"all\"\n" +
                "      },\n" +
                "      \"business\": {\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"ik_max_word\",\n" +
                "        \"index\": true,\n" +
                "        \"copy_to\": \"all\"\n" +
                "      },\n" +
                "      \"pic\": {\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": false\n" +
                "      },\n" +
                "      \"location\": {\n" +
                "        \"type\": \"geo_point\",\n" +
                "        \"index\": false\n" +
                "      },\n" +
                "      \"isAD\": {\n" +
                "        \"type\": \"boolean\",\n" +
                "        \"index\": true\n" +
                "      },\n" +
                "      \"all\": {\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"ik_max_word\",\n" +
                "        \"index\": true\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}", XContentType.JSON);
     */
    // 发送带有映射树的创建索引库请求, 并接收创建索引库请求的响应
    CreateIndexResponse createIndexResponse = indicesObject.create(createIndexRequest, RequestOptions.DEFAULT);
    // 是否创建成功
    log.info("\n索引库是否创建成功: {}", createIndexResponse.isAcknowledged());
    log.info("\n响应结果: {}", createIndexResponse);
}

GET

获取索引库映射

    @Test
    public void getIndex() throws Exception {
        // 获取查询索引库对象, 并指定索引库
        GetIndexRequest maomaoIndex = new GetIndexRequest("hotel");

        // 发送查询索引库请求
        GetIndexResponse getIndexResponse = restHighLevelClient.indices().get(maomaoIndex, RequestOptions.DEFAULT);

        // 获取索引树, 先获取索引库, 在获取SourceAsMap, 再获取properties中的属性列表
        Object mappings = getIndexResponse.getMappings().get("hotel").getSourceAsMap().get("properties");

        // 转换为Json
        String jsonString = JSON.toJSONString(mappings);

        log.info("Json: " + jsonString);
    }

Delete

删除指定的索引库

删除指定索引库

@Test
public void deleteIndexTest() throws Exception {
    // 获取删除索引库对象
    IndicesClient indicesObject = highLevelClient.indices();
    // 新建删除索引库请求: 删除一个指定名称的索引库
    DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("hotel");
    // 发出删除索引库请求, 并接受删除索引库请求的响应
    AcknowledgedResponse deleteIndexResponse = indicesObject.delete(deleteIndexRequest, RequestOptions.DEFAULT);
    // 判断是否删除成功
    log.info("\n Hotel索引库是否删除成功: {}", deleteIndexResponse.isAcknowledged());
    log.info("\n响应结果: {}", deleteIndexResponse);
}

对文档作: 增、删、改、查

Insert / Update (ES处理修改时, 是作覆盖式修改)

批量添加 (方案一)

导入数据库中的数据到ES中 (批量导入)

    public void createIndexWithMappingWithImportData() throws Exception {
        // 获取索引库操作对象
        IndicesClient indicesObject = highLevelClient.indices();

        // 创建索引库
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("hotel");

        // 创建映射
        createIndexRequest.mapping(
                "{\n" +
                        "    \"properties\": {\n" +
                        "      \"id\": {\n" +
                        "        \"type\": \"keyword\"\n" +
                        "      },\n" +
                        "      \"name\": {\n" +
                        "        \"type\": \"text\",\n" +
                        "        \"analyzer\": \"ik_max_word\",\n" +
                        "        \"copy_to\": \"all\"\n" +
                        "      },\n" +
                        "      \"address\": {\n" +
                        "        \"type\": \"text\",\n" +
                        "        \"analyzer\": \"ik_max_word\"\n" +
                        "      },\n" +
                        "      \"price\": {\n" +
                        "        \"type\": \"integer\"\n" +
                        "      },\n" +
                        "      \"score\": {\n" +
                        "        \"type\": \"integer\"\n" +
                        "      },\n" +
                        "      \"brand\": {\n" +
                        "        \"type\": \"text\",\n" +
                        "        \"analyzer\": \"ik_max_word\",\n" +
                        "        \"copy_to\": \"all\"\n" +
                        "      },\n" +
                        "      \"city\": {\n" +
                        "        \"type\": \"keyword\"\n" +
                        "      },\n" +
                        "      \"starName\": {\n" +
                        "        \"type\": \"keyword\"\n" +
                        "      },\n" +
                        "      \"business\": {\n" +
                        "        \"type\": \"keyword\",\n" +
                        "        \"copy_to\": \"all\"\n" +
                        "      },\n" +
                        "      \"location\": {\n" +
                        "        \"type\": \"geo_point\"\n" +
                        "      },\n" +
                        "      \"pic\": {\n" +
                        "        \"type\": \"keyword\",\n" +
                        "        \"index\": false\n" +
                        "      }, \n" +
                        "      \"isAD\": {\n" +
                        "        \"type\": \"boolean\"\n" +
                        "      },\n" +
                        "      \"all\": {\n" +
                        "        \"type\": \"text\",\n" +
                        "        \"analyzer\": \"ik_max_word\"\n" +
                        "      }\n" +
                        "    }\n" +
                        "  }",
                XContentType.JSON
        );

        // 发送索引库创建请求
        CreateIndexResponse createIndexResponse = indicesObject.create(createIndexRequest, RequestOptions.DEFAULT);

        log.info("\n索引库创建结果: {}", createIndexResponse.isAcknowledged());

        log.info("\n响应结果: {}", createIndexResponse);

        // 查询数据库
        List<Hotel> hotels = hotelMapper.selectList(null);

        // Copy 到 HotelDoc
        hotels.forEach(hotel -> {
            try {
                // 将Hotel Copy To HotelDoc 中
                HotelDoc hotelDoc = new HotelDoc(hotel);

                // 创建文档
                IndexRequest hotelIndex = new IndexRequest("hotel").id(hotel.getId().toString());

                // 将HotelDoc转换为Json
                String hotelDocToJson = objectMapper.writeValueAsString(hotelDoc);

                // 填充内容
                hotelIndex.source(hotelDocToJson, XContentType.JSON);

                // 发送文档创建请求
                IndexResponse indexResponse = highLevelClient.index(hotelIndex, RequestOptions.DEFAULT);


                // 获取创建后的文档id
                log.info("ES文档, id: {}",indexResponse.getId());

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

批量添加 (方案二)

批量添加 (方案二)

@Test
public void BulkSearchDocument() throws Exception {
    // 查询数据库中的所有数据
    List<Hotel> hotels = hotelMapper.selectList(null);
    // 获取批量添加对象
    BulkRequest bulkRequest = new BulkRequest();
    // 遍历所有数据
    hotels.forEach(hotel -> {
        try {
            // 查询所有数据
            HotelDoc hotelDoc = new HotelDoc(hotel);
            // 将查询的结果转换为Json
            String hotelDocToJson = objectMapper.writeValueAsString(hotelDoc);
            // 设定指定索引库 及 文档id
            IndexRequest indexRequest = new IndexRequest("hotel").id(hotel.getId().toString());
            // 将Json添加到IndexRequest请求中
            indexRequest.source(hotelDocToJson, XContentType.JSON);
            // 添加请求
            bulkRequest.add(indexRequest);
        }catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    });
    // 发送批量添加请求
    BulkResponse bulkResponse = highLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    log.info("批量添加结果: {}", bulkResponse.status());
}

Query

查询指定文档id

指定文档id, 查询文档

public void queryDocument() throws Exception {
    // 指定索引库民初, 获取查询文档的请求对象
    GetRequest hotel = new GetRequest("hotel").id("36934");
    // 发送查询请求
    GetResponse getResponse = highLevelClient.get(hotel, RequestOptions.DEFAULT);
    // 获取查询结果
    String sourceAsString = getResponse.getSourceAsString();
    // 将Json转换为HotelDoc实体类
    HotelDoc hotelDoc = objectMapper.readValue(sourceAsString, HotelDoc.class);
    log.info("hotelDoc: {}", hotelDoc);
}

Delete

删除指定文档id

删除指定文档id

public void deleteDocument() throws Exception {
    // 获取指定索引库, 且指定文档id的删除文档对象
    var deleteRequest = new DeleteRequest("hotel").id("36934");
    // 发送删除文档请求
    DeleteResponse deleteResponse = highLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
    log.info("deleteResponse: {}", deleteResponse.getId());
}

条件查询

查询所有 (没有特定条件)

public void queryAllDocument() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件: 查询所有
    SearchSourceBuilder matchAllQuery = searchRequest.source().query(QueryBuilders.matchAllQuery());
    
    // 设置展示的条目
    searchRequest.source().size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 处理查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 获取查询结果集
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取文档内容Json
        String searchResult = hit.getSourceAsString();
        // 将Json转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 添加到集合中
        hotelDocs.add(hotelDoc);
    }
    // 全文查询状态
    log.info("\n查询全部状态: {}", searchResponse.status());
    
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n查询全部结果: {}", hotelDoc));
}

单字段查询

public void queryOneDocument() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件: 单字段查询
    searchRequest.source().query(QueryBuilders.matchQuery("all", "如家"));
    // 设置展示条目
    searchRequest.source().size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 收集结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询的结果
        String searchResult = hit.getSourceAsString();
        // 将结果(Json串) 转换为 JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        hotelDocs.add(hotelDoc);
    }
    // 单字段查询状态
    log.info("\n单字段查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n单字段查询结果: {}", hotelDoc));
}

多字段查询

public void queryManyDocuments() throws Exception {
    // 获取查询请求对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件: 多字段查询
    searchRequest.source().query(QueryBuilders.multiMatchQuery("如家", "name", "brand"));
    // 设置展示条目
    searchRequest.source().size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 收集结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取结果
        String searchResult = hit.getSourceAsString();
        // 将查询结果转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        hotelDocs.add(hotelDoc);
    }
    // 多字段查询状态
    log.info("\n多字段查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n多字段查询结果: {}", hotelDoc));
}

精准查询 (不会对查询条件分词)

Term (精准值查询)
@Test
public void termSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    TermQueryBuilder queryBuilder = QueryBuilders.termQuery("name", "如家");
    searchRequest.source().query(queryBuilder);
    // 设置页面大小
    searchRequest.source().size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 收集查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        hotelDocs.add(hotelDoc);
    }
    // 精确查询状态
    log.info("\n精确查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n精确查询结果: {}", hotelDoc));
}
Range (范围查询)
@Test
public void rangeSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件: gte: 大于等于, lte: 小于等于
    searchRequest.source().query(QueryBuilders.rangeQuery("price").gte(99).lte(199));
    searchRequest.source().size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 收集查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        hotelDocs.add(hotelDoc);
    }
    // 范围查询状态
    log.info("\n范围查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n范围查询结果: {}", hotelDoc));
}

地理位置查询

圆形
public void geoDistanceSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .query(
                    QueryBuilders.geoDistanceQuery("location")
                            .point(
                                    new GeoPoint(31.21, 121.5)).
                            distance("15km")
            )
            .size(1000);
    // 发送查询条件
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 收集查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json转换JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 添加到集合
        hotelDocs.add(hotelDoc);
    }
    // 地理坐标查询状态
    log.info("\n地理坐标查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n地理坐标查询结果: {}", hotelDoc));
}
矩形
public void geoBoundingBoxSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .query(
                    QueryBuilders.geoBoundingBoxQuery("location")
                            .setCorners(
                                    new GeoPoint(31.1, 121.5),
                                    new GeoPoint(30.9, 121.7)
                            )
            )
            .size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 接收结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 添加到集合
        hotelDocs.add(hotelDoc);
    }
    // 地理坐标查询状态
    log.info("\n地理坐标查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n地理坐标查询结果: {}", hotelDoc));
}

组合条件查询

查询全国的酒店名称不为七天的上海的所有酒店, 价格范围大于等于99, 小于等于199, 而且查询的地址位置是31,21, 121.5, 范围半径20km

@Test
public void boolSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .query(
                    QueryBuilders.boolQuery()
                            .must(
                                    QueryBuilders.rangeQuery("price")
                                            .gte(99)
                                            .lte(199))
                            .mustNot(
                                    QueryBuilders.termQuery("name", "七天"))
                            .filter(
                                    QueryBuilders.geoDistanceQuery("location")
                                            .point(31.21, 121.5)
                                            .distance("20km")
                            )
                            .should(
                                    QueryBuilders.termQuery("city", "上海")
                            )
            )
            .size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 接收查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    for (SearchHit hit : searchResponse.getHits()) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json 转换为 JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 添加查询结果
        hotelDocs.add(hotelDoc);
    }
    // 组合条件查询状态
    log.info("\n组合条件查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n组合条件查询结果: {}", hotelDoc));
}

算分查询

查询如家酒店, 对于深圳的如家进行+10分

public void addScoreSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .query(
                    QueryBuilders.functionScoreQuery(
                            QueryBuilders.matchQuery("all", "如家"),
                            new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                                    new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                            QueryBuilders.termQuery("city", "深圳")
                                            ,ScoreFunctionBuilders.weightFactorFunction(10f)
                                    )
                            }
                    )
                            .boostMode(CombineFunction.SUM)
            )
            .size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 接收查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    for (SearchHit hit : searchResponse.getHits()) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json 转换为 JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 添加查询结果
        hotelDocs.add(hotelDoc);
    }
    // 算分查询状态
    log.info("\n算分查询状态: {}", searchResponse.status());
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n算分查询结果: {}", hotelDoc));
}

排序查询

地理位置排序查询

查找离设定经纬度坐标最近的如家酒店

@Test
public void orderSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .query(
                    QueryBuilders.matchQuery("all", "如家")
            )
            .sort(
                    SortBuilders.geoDistanceSort("location", new GeoPoint(39.76, 116.33)) // SortBuilders.geoDistanceSort("location", 39.76, 116.33) 两者结果一致
                            .order(SortOrder.ASC)
                            .unit(DistanceUnit.KILOMETERS)
            )
            .size(1000)
            .from(0)    // 从第一页开始查询
            .size(7)    // 每次查询7条, 类似于mysql中的limit, 使用了这个, 就会覆盖query下的size, DSL语句会报错, 但JavaCode不会
    ;
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 地理位置排序查询状态
    log.info("\n地理位置排序查询状态: {}", searchResponse.status());
    // 地理位置排序查询总条目
    log.error("\n地址位置排序查询总条目: {}", hits.getTotalHits().value);
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // 获取查询出的酒店位置距离设定的位置有多远
        Object[] sortValues = hit.getSortValues();
        // 若不是经纬度查询, 则距离值则为空, 直接Json转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 输出查询结果
        log.info("\n查询结果: {}", hotelDoc);
        log.info("距离设定的位置有: {}km", sortValues[0]);
    }
}

指定字段排序查询

倒序查询全国所有如家品牌酒店的价格

@Test
public void sortSearchAll() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .query(
                    QueryBuilders.matchQuery("all", "如家")
            )
            .sort(
                    SortBuilders.fieldSort("price")
                            .order(SortOrder.DESC)
            )
            .size(1000);
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 收集查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 添加到集合
        hotelDocs.add(hotelDoc);
    }
    // 指定字段排序查询状态
    log.info("\n地理位置排序查询状态: {}", searchResponse.status());
    // 指定字段排序查询总条目
    log.error("\n指定字段排序查询总条目: {}", hits.getTotalHits().value);
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n指定字段排序查询结果: {}", hotelDoc));
}

高亮显示

查询如家酒店, 并高亮显示为粉色

@Test
public void highlightSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .query(
                    QueryBuilders
                            .matchQuery("all", "如家")
            )
            .from(6) // 显示第2页数据
            .size(7) // 只显示7条
            .highlighter(
                    SearchSourceBuilder
                            .highlight()
                            .field("name")
                            .requireFieldMatch(false)
                            .preTags("<font color = 'pink'>")
                            .postTags("</font>")
            );
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 收集查询结果
    ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
    // 处理查询结果
    SearchHits hits = searchResponse.getHits();
    // 遍历结果集
    for (SearchHit hit : hits) {
        // 获取查询结果
        String searchResult = hit.getSourceAsString();
        // Json转换为JavaBean
        HotelDoc hotelDoc = objectMapper.readValue(searchResult, HotelDoc.class);
        // 处理高亮结果: 获取需要高亮的字段
        HighlightField nameHighlightField = hit.getHighlightFields().get("name");
        // 判断HighlightField对象不为空, ObjectUtil是MyBatisPlus的工具类
        if (ObjectUtils.isEmpty(nameHighlightField)) {
            // 获取第一个元素内容
            Text newValue = nameHighlightField.getFragments()[0];
            // 将Json转换后的JavaBean中指定的属性替换为新的值
            hotelDoc.setName(newValue.toString());
        }
        // 添加到集合
        hotelDocs.add(hotelDoc);
    }
    // 指定字段高亮显示查询状态
    log.info("\n指定字段高亮显示查询状态: {}", searchResponse.status());
    // 指定字段高亮显示查询总条目
    log.error("\n指定字段高亮显示查询总条目: {}", hits.getTotalHits().value);
    // 输出所有查询结果
    hotelDocs.forEach(hotelDoc -> log.info("\n指定字段高亮显示查询结果: {}", hotelDoc));
}

聚合查询

Bucket (桶查询)

聚合查询: 桶聚合, 查询全国每个城市的酒店数量

@Test
public void bucketSearch() throws Exception {
    // 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    // 构建查询条件
    searchRequest.source()
            .size(0)
            .aggregation(
                    AggregationBuilders
                            .terms("cityCountAgg") // 桶名称
                            .field("city")	// 统计字段
                            .order(
                                    BucketOrder
                                            .count(true) // true = asc, false = desc
                            )
                            .size(7) // 只展示7条数据
            );
    // 发送查询请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 处理查询结果: 接收结果必须使用Terms, 并且是ElasticSearch包中的
    Terms cityCountAgg = searchResponse.getAggregations().get("cityCountAgg");
    // 获取桶
    List<? extends Terms.Bucket> cityBuckets = cityCountAgg.getBuckets();
    // 遍历结果集
    for (Terms.Bucket cityBucket : cityBuckets) {
        // 获取统计到的城市名称
        String cityName = cityBucket.getKeyAsString();
        // 获取统计到的城市的所有酒店数量
        long cityCount = cityBucket.getDocCount();
        log.info("统计到的城市名称: {}", cityName);
        log.info("获取统计到的城市的所有酒店数量: {}", cityCount);
    }
}

自动补全

@Test
public void autoCompletionSearch() throws Exception {
	// 获取查询对象
    SearchRequest searchRequest = new SearchRequest("hotel");
    //添加自动补全的查询条件
    searchRequest.source()
            .suggest(
                    new SuggestBuilder()
                            .addSuggestion(
                                    "searchSuggetion"
                                    ,SuggestBuilders
                                            .completionSuggestion("suggestion")
                                            .prefix("如")
                                            .skipDuplicates(true)
                                            .size(33)
                            )
            );
    //发出请求
    SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    // 处理结果集
    CompletionSuggestion searchSuggetion = searchResponse.getSuggest().getSuggestion("searchSuggetion");
    List<CompletionSuggestion.Entry.Option> options = searchSuggetion.getOptions();
    List<String> result = new ArrayList<>();
    //遍历options取出所有的提示内容存储到集合中,返回
    for (CompletionSuggestion.Entry.Option option : options) {
        result.add(option.getText().toString());
    }
    log.info("\n自动补全查询结果: {}", result);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要对百万数据的 Elasticsearch 索引进行重命名,可以尝试以下性能优化方法: 1. 执行重命名操作时,尽量避免在同一节点上同时执行其他繁重的操作,以减少节点的负载和竞争。 2. 可以考虑将索引分成多个分片,然后在多个节点上执行并行的重命名操作。这可以通过设置索引的分片数来实现,例如: ``` PUT /my_index/_settings { "index": { "number_of_shards": 5 } } ``` 这将将索引分成 5 个分片,每个分片都可以在不同的节点上处理。 3. 使用 Elasticsearch Bulk API 执行批量操作。Bulk API 可以一次性处理多个操作,从而提高索引重命名的性能,例如: ``` POST /_bulk { "update": { "_id": "1", "_index": "my_index", "_type": "_doc" } } { "doc": { "name": "new_name" } } { "update": { "_id": "2", "_index": "my_index", "_type": "_doc" } } { "doc": { "name": "new_name" } } ... ``` 这将在一次 API 调用中更新多个文档的名称,而不是逐个更新。 4. 在执行重命名操作之前,可以考虑关闭索引的刷新机制。刷新操作会将新数据写入磁盘,从而增加索引重命名的时间和开销。可以使用以下命令关闭索引的刷新机制: ``` POST /my_index/_settings { "index": { "refresh_interval": "-1" } } ``` 这将关闭索引的刷新机制。在执行完索引重命名操作后,可以使用以下命令重新启用刷新机制: ``` POST /my_index/_settings { "index": { "refresh_interval": "1s" } } ``` 这将每秒钟执行一次索引刷新操作。请注意,关闭刷新机制可能会导致某些查询结果不准确,因为查询可能会返回尚未刷新的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cherish Xin And Meng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值