ElasticSearch(九)【SpringBoot整合】

九、SpringBoot整合Elasticsearch


上一篇文章ElasticSearch - 过滤查询

9.1 基本环境配置

  1. 创建一个springboot工程springboot-elasticsearch
  2. pom.xml导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

注意】使用的springboot需要根当前ES版本兼容

在这里插入图片描述

  1. 配置application.yml文件
# 应用名称
spring:
  application:
    name: springboot-elasticsearch
# web端口号
server:
  port: 3035
# 自定义es主机和端口号:
es:
  host: 192.168.159.100:9200
  1. 配置客户端

创建config包,添加配置类RestClientConfiguration.class

package com.vinjcent.config;

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;

// ES 配置类
@Configuration
public class RestClientConfiguration extends AbstractElasticsearchConfiguration {

    @Value("${es.host}")
    private String host;

    @Bean
    @Override   // ES 两个端口,一个是9200(rest方式通信),一个是9300(tcp方式通信)
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(host)
                .build();
        return RestClients.create(clientConfiguration).rest();
    }
}

配置完之后,该配置类不仅会创建RestHighLevelClient的bean,还会帮我们创建一个叫做ElasticsearchOperations客户端对象

为什么要提供这两个对象呢?

因为Spring Data在封装ES操作的时候,完全站在了两个角度去考虑

  • ElasticsearchOperations这个bean在操作ES的时候,主要以对象作为基础去操作,ElasticsearchOperations序列化对象之后传递给ES,ES在查询到结果之后,反序列化传递给ElasticsearchOperations
  • RestHighLevelClient更像于可视化的Kibana,通过rest的方式与ES进行交互(企业多用,推荐使用)

9.2 ElasticsearchOperations

  • 特点:始终使用面向对象方式操作ES
    • 索引:用来存放相似文档的集合
    • 映射:用来决定放入文档的每个字段以什么样方式录入到ES中,字段类型、字段分词器…
    • 文档:可以被索引最小单元,json数据格式

使用ElasticsearchOperations进行增删查改操作

  1. 创建一个Product实体类
package com.vinjcent.pojo;


import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.io.Serializable;

/**
 * @Document: 将这个类对象转为 es 中一条文档进行录入
 * indexName: 用来指定文档的索引名称
 * createIndex: 用来指定是否创建索引,默认为false
 */
@Document(indexName = "products", createIndex = true)
public class Product implements Serializable {

    @Id // 用来将放入对象id值作为文档_id进行映射
    private Integer id;

    @Field(type = FieldType.Keyword)    // 字段映射类型
    private  String title;

    @Field(type = FieldType.Double)
    private Double price;

    @Field(type = FieldType.Text)
    private String description;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", price=" + price +
                ", description='" + description + '\'' +
                '}';
    }
}

  1. 在使用SpringBoot操作之前,将索引记录删除
# 查询索引
GET /_cat/indices?v

# 删除索引
DELETE /product

# 查看索引映射
GET /products/_mapping

# 查看数据
GET /products/_search
{
  "query": {
    "match_all": {}
  }
}
  1. 使用Java操作ES进行增、删、查、改、
package com.vinjcent;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vinjcent.pojo.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Query;

@SpringBootTest
public class ElasticSearchOperationsTest{

    private final ElasticsearchOperations elasticsearchOperations;

    @Autowired
    public ElasticSearchOperationsTest(ElasticsearchOperations elasticsearchOperations) {
        this.elasticsearchOperations = elasticsearchOperations;
    }

    /**
     * save 索引一条文档 或 更新一条文档
     * save 方法当文档id不存在时添加文档,当文档id存在时候更新文档
     */
    @Test
    public void testSave() {
        Product product = new Product();
        product.setId(1);
        product.setPrice(2.5);
        product.setTitle("vinjcent的妙妙屋");
        product.setDescription("真是米奇妙妙屋,妙到了家");
        elasticsearchOperations.save(product);
    }

    /**
     * query 根据id查询一条文档
     */
    @Test
    public void testQuery() {
        Product product = elasticsearchOperations.get("1", Product.class);
        System.out.println(product);
    }

    /**
     * delete 根据id删除一条文档
     */
    @Test
    public void testDelete() {
        Product product = new Product();
        product.setId(1);
        String delete = elasticsearchOperations.delete(product);
        System.out.println(delete);
    }

    /**
     * delete 删除所有
     */
    @Test
    public void testDeleteAll() {
        elasticsearchOperations.delete(Query.findAll(), Product.class);
    }

    /**
     * 查询所有
     */
    @Test
    public void testQueryAll() throws JsonProcessingException {
        SearchHits<Product> productSearchHits = elasticsearchOperations.search(Query.findAll(), Product.class);
        System.out.println("总分数: " + productSearchHits.getMaxScore());
        System.out.println("符合条件总数: " + productSearchHits.getTotalHits());
        for (SearchHit<Product> productSearchHit : productSearchHits) {
            System.out.println(new ObjectMapper().writeValueAsString(productSearchHit.getContent()));
        }
    }

}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

9.3 RestHighLevelClient

使用RestHighLevelClient进行索引操作

  1. 在使用SpringBoot操作之前,将索引记录删除
# 查询索引
GET /_cat/indices?v

# 删除索引
DELETE /products

# 查看数据
GET /products/_search
{
  "query": {
    "match_all": {}
  }
}
  1. 测试类RestHighLevelClientTests.class
package com.vinjcent;

import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
public class RestHighLevelClientTests {

    private final RestHighLevelClient restHighLevelClient;

    @Autowired
    public RestHighLevelClientTests(@Qualifier("elasticsearchClient") RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }

    /**
     * 创建索引、映射
     */
    @Test
    public void testIndexAndMapping() throws IOException {

        // 1.创建索引请求对象
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("products");
        // 2.指定映射,参数1: 指定映射json结构     参数2: 指定映射类型
        createIndexRequest.mapping("{\n" +
                "    \"properties\": {\n" +
                "      \"title\": {\n" +
                "        \"type\": \"keyword\"\n" +
                "      },\n" +
                "      \"price\": {\n" +
                "        \"type\": \"double\"\n" +
                "      },\n" +
                "      \"create_time\": {\n" +
                "        \"type\": \"date\"\n" +
                "      },\n" +
                "      \"description\": {\n" +
                "        \"type\": \"text\", \n" +
                "        \"analyzer\": \"ik_max_word\"\n" +
                "      }\n" +
                "    }\n" +
                "  }", XContentType.JSON);

        // 参数1: 创建索引请求对象    参数2: 请求配置对象
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        System.out.println("创建状态: " + createIndexResponse.isAcknowledged());

        restHighLevelClient.close();    // 关闭资源
    }

    /**
     * 删除索引
     * @throws IOException
     */
    @Test
    public void testDeleteIndex() throws IOException {
        // 参数1: 创建索引请求对象    参数2: 请求配置对象
        AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().delete(new DeleteIndexRequest("products"), RequestOptions.DEFAULT);
        System.out.println(acknowledgedResponse.isAcknowledged());
    }


}

在这里插入图片描述

在这里插入图片描述

使用RestHighLevelClient进文档操作

package com.vinjcent;

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.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
public class RestHighLevelClientForDocumentTests {

    private final RestHighLevelClient restHighLevelClient;

    @Autowired
    public RestHighLevelClientForDocumentTests(@Qualifier("elasticsearchClient") RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }

    /**
     * 创建一条文档
     * @throws IOException
     */
    @Test
    public void testCreateDocu() throws IOException {
        // 1.创建索引对象
        IndexRequest indexRequest = new IndexRequest("products");
        // 2.配置创建的文档对象
        indexRequest.id("1")    // 手动指定文档的id
                .source("{\n" +     // 文档的数据内容
                "  \"title\": \"vinjcent米奇妙妙屋\",\n" +
                "  \"price\": 21.5,\n" +
                "  \"create_time\": \"2022-09-16\",\n" +
                "  \"description\": \"真是妙到家了!\"\n" +
                "}",XContentType.JSON);
        // 3.接收请求后的索引响应对象,参数1: 索引请求对象  参数2: 请求配置对象
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);

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

    /**
     * 更新一条文档
     * @throws IOException
     */
    @Test
    public void testUpdateDocu() throws IOException {

        // 1.创建更新请求对象
        UpdateRequest updateRequest = new UpdateRequest("products", "2");

        // 2.配置doc文档对象
        updateRequest.doc("{\n" +
                "    \"title\": \"totoro--的米奇妙妙屋\"\n" +
                "  }", XContentType.JSON);

        // 参数1: 更新请求对象  参数2: 请求配置对象
        UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);

        System.out.println(updateResponse.status());
    }

    /**
     * 删除一条文档
     * @throws IOException
     */
    @Test
    public void testDeleteDocu() throws IOException {

        // 参数1: 更新请求对象  参数2: 请求配置对象
        DeleteResponse deleteResponse = restHighLevelClient.delete(new DeleteRequest("products", "2"), RequestOptions.DEFAULT);
        System.out.println(deleteResponse.status());
    }

    /**
     * 基于id查询一条文档
     * @throws IOException
     */
    @Test
    public void testQueryByIdDocu() throws IOException {
	    // 1.声明get请求对象
        GetRequest getRequest = new GetRequest("products", "1");
        // 2.接收响应对象		参数1: 获取请求对象  参数2: 请求配置对象
        GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);

        System.out.println("id: " + getResponse.getId());

        System.out.println("source: " + getResponse.getSourceAsString());


    }


}

9.4 RestHighLevelClient 查询操作

package com.vinjcent;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
public class RestHighLevelClientForDocumentTests {

    private final RestHighLevelClient restHighLevelClient;

    @Autowired
    public RestHighLevelClientForDocumentTests(@Qualifier("elasticsearchClient") RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }

    /**
     * 查询所有
     */
    @Test
    public void testMatchAll() throws IOException {
        // 1.搜索请求对象
        SearchRequest searchRequest = new SearchRequest("products");

        // 2.指定条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 3.配置请求对象中的条件对象
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());  // 查询所有
        searchRequest.source(searchSourceBuilder);

        // 参数1: 搜索的请求对象     参数2: 请求配置对象     返回值: 擦汗寻结果对象
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());

        // 获取结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String id = hit.getId();
            System.out.println("source: " + hit.getSourceAsString());
        }
    }

    /**
     * 关键字查询 term
     */
    @Test
    public void testTerm() throws IOException {
        query(QueryBuilders.termQuery("description","真是"));
    }

    /**
     * 范围查询 range
     */
    @Test
    public void testRange() throws IOException {
        query(QueryBuilders.rangeQuery("price").gt(0).lt(50));
    }

    /**
     * 前缀查询 prefix
     */
    @Test
    public void testPrefix() throws IOException {
        query(QueryBuilders.prefixQuery("title", "vinjcent"));
    }

    /**
     * 通配符查询 wildcard
     */
    @Test
    public void testWildcard() throws IOException {
        // "*"代表多个字符,"?"代表一个字符
        query(QueryBuilders.wildcardQuery("title", "vinjcent*"));
    }

    /**
     * 多id查询 ids
     */
    @Test
    public void testIds() throws IOException {
        // "*"代表多个字符,"?"代表一个字符
        query(QueryBuilders.idsQuery().addIds("1","2"));
    }

    /**
     * 多字段查询 multi_match
     */
    @Test
    public void testMultiMatch() throws IOException {
        // 如果查的字段分词,会先进行分词处理,否则不进行分词处理
        query(QueryBuilders.multiMatchQuery("妙", "title","description"));
    }


    public void query(QueryBuilder queryBuilder) throws IOException {

        // 1.搜索请求对象
        SearchRequest searchRequest = new SearchRequest("products");

        // 2.指定条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 3.配置请求对象中的条件对象
        searchSourceBuilder.query(queryBuilder);  // 关键字
        searchRequest.source(searchSourceBuilder);

        // 参数1: 搜索的请求对象     参数2: 请求配置对象     返回值: 擦汗寻结果对象
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());

        // 获取结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println("id: " + hit.getId() + " source: " + hit.getSourceAsString());
        }
    }
}

9.5 RestHighLevelClient 高亮、分页、排序

package com.vinjcent;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
public class RestHighLevelClientForDocumentTests {

    private final RestHighLevelClient restHighLevelClient;

    @Autowired
    public RestHighLevelClientForDocumentTests(@Qualifier("elasticsearchClient") RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }


    /**
     * 分页查询     from 起始位置   size 分页大小
     * 排序查询     sort
     * 指定字段获取   _source
     * 高亮查询     highlight
     * @throws IOException
     */
    @Test
    public void testSearch() throws IOException {

        // 1.创建请求索引对象
        SearchRequest searchRequest = new SearchRequest("products");
        // 2.创建搜索条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3.创建高亮对象
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.requireFieldMatch(false)   // 注意: 开启高亮的字段必须可以分词,不然查询结果无效
                .preTags("<span style='color: red;'>")  // 配置高亮包裹前缀
                .postTags("</span>")                    // 配置高亮包裹后缀
                .field("description")                   // 指定高亮字段
                .field("title");                        // 指定高亮字段
        searchSourceBuilder.query(QueryBuilders.termQuery("description", "妙"))
                            .from(0)    // 起始位置
                            .size(2)    // 分页大小,默认返回是10条
                            .sort("price", SortOrder.DESC) // 指定排序字段以及排序方式
                            .fetchSource(null, new String[]{"create_time"})  // 参数1: 包含字段数组  参数2: 排除字段数组  注意,当两者结合使用时,只有前者会生效
                            .highlighter(highlightBuilder);
        // 4.为请求对象配置搜素对象
        searchRequest.source(searchSourceBuilder);
        // 5.接收响应对象
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());

        // 获取结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println("id: " + hit.getId() + " source: " + hit.getSourceAsString());
            // 获取高亮字段description
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields.containsKey("description")) {
                System.out.println("description高亮结果: " + highlightFields.get("description").fragments()[0]);    // 获取的字段为数组形式
            }
            // 获取高亮字段title
            if (highlightFields.containsKey("title")) {
                System.out.println("title高亮结果: " + highlightFields.get("title").fragments()[0]);    // 获取的字段为数组形式
            }
        }
    }
}

9.6 RestHighLevelClient 过滤查询

package com.vinjcent;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
public class RestHighLevelClientForDocumentTests {

    private final RestHighLevelClient restHighLevelClient;

    @Autowired
    public RestHighLevelClientForDocumentTests(@Qualifier("elasticsearchClient") RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }


    /**
     * query    精确查询,查询计算文档得分,并根据文档得分进行返回
     * filter query   过滤查询,用来在大量数据中筛选出本地查询相关数据,不会计算文档得分,会对数据进行缓存
     * 注意: 当两种查询一起使用时,ES优先执行filter query,后执行query
     */
    @Test
    public void testFilterQuery() throws IOException {

        // 1.创建请求索引对象
        SearchRequest searchRequest = new SearchRequest("products");
        // 2.创建搜索条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3.配置查询条件
        searchSourceBuilder
                .query(QueryBuilders.matchAllQuery())
                // ids、exists、term、terms、range等等都可以修改
                .postFilter(QueryBuilders.termQuery("description", "妙"));

        // 4.为请求对象配置搜素对象
        searchRequest.source(searchSourceBuilder);
        // 5.接收响应对象
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());

        // 获取结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println("id: " + hit.getId() + " source: " + hit.getSourceAsString());
        }
    }


}

9.7 RestHighLevelClient 应用使用JSON

package com.vinjcent;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.vinjcent.pojo.Product;
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.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
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.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
public class RestHighLevelClientForDocumentTests {

    private final RestHighLevelClient restHighLevelClient;

    @Autowired
    public RestHighLevelClientForDocumentTests(@Qualifier("elasticsearchClient") RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }


    /**
     * 在有索引映射的条件下
     * 将对象放入ES中,进行序列化操作
     */
    @Test
    public void testAddDoc() throws IOException {
        Product product = new Product();
        product.setId(2);
        product.setPrice(5.2);
        product.setTitle("vinjcent米奇妙妙屋");
        product.setDescription("我的心可不冷");

        IndexRequest indexRequest = new IndexRequest("products");
        indexRequest.id(product.getId().toString())
                .source(new ObjectMapper().writeValueAsString(product), XContentType.JSON); // 使用spring中自带的json对象转换
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(indexResponse.status());
    }

    /**
     * 将对象从ES中读取,进行反序列化
     */
    @Test
    public void testGetDoc() throws IOException {
        // 1.创建请求对象
        SearchRequest searchRequest = new SearchRequest("products");

        // 2.创建搜索条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3. 高亮对象
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder
                .requireFieldMatch(false)
                .field("description")
                .preTags("<span style='color: red;'>")
                .postTags("</span>");
        // 4.指定查询条件
        searchSourceBuilder
                .query(QueryBuilders.termQuery("description", "绝境"))
                .from(0)
                .size(10)
                .highlighter(highlightBuilder);
        // 5.为请求对象配置条件对象
        searchRequest.source(searchSourceBuilder);
        // 6.接收响应对象
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());

        List<Product> products = new ArrayList<>();
        // 获取响应结果对象
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());    // json格式
            Product product = new ObjectMapper().readValue(hit.getSourceAsString(), Product.class); // 将json转为Product对象

            // 处理高亮
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields.containsKey("description")) {
                // 获取高亮后的属性值,进行修改
                product.setDescription(highlightFields.get("description").fragments()[0].toString());
            }

            products.add(product);

        }

        for (Product product : products) {
            System.out.println(product);
        }

    }
}

下一篇文章ElasticSearch - 聚合查询

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Elasticsearch是一个开源的分布式全文搜索和分析引擎,而Spring BootJava开发的一种快速开发框架。将两者整合可以提供一个强大的搜索和分析功能的应用程序。 使用Spring Boot整合Elasticsearch的过程如下: 1. 首先,在pom.xml文件中添加ElasticsearchSpring Boot相关的依赖项。例如,添加spring-boot-starter-data-elasticsearch依赖来使用Spring Data Elasticsearch模块。 2. 在应用程序的配置文件中,配置Elasticsearch的连接参数,如主机地址、端口号等。可以使用Spring Boot的配置注解来简化配置过程。 3. 创建一个实体类,使用注解定义其映射到Elasticsearch索引的方式。可以使用@Document注解设置索引名称、类型等属性,使用@Field注解设置字段的映射方式。 4. 创建一个Elasticsearch的Repository接口,继承自Spring Data Elasticsearch提供的ElasticsearchRepository接口。可以使用该接口提供的方法来进行索引的增删改查操作。 5. 在需要使用Elasticsearch的业务逻辑中,注入创建的Repository接口实例,通过调用其方法来实现对索引的操作。例如,可以使用save方法保存实体对象到索引中,使用deleteById方法删除索引中的记录。 通过以上步骤,就可以实现ElasticsearchSpring Boot整合。使用Spring Boot可以极大地简化了配置和开发的过程,而Elasticsearch提供了强大的全文搜索和分析功能,可以为应用程序提供高效的搜索和查询性能。整合后的应用程序可以方便地使用Elasticsearch进行数据索引和搜索操作。 ### 回答2: Elasticsearch是一个开源的搜索引擎,可以用于处理大量数据的搜索、分析和存储。Spring Boot是一个用于快速构建应用程序的框架,可以简化开发过程并提供各种强大功能。 将ElasticsearchSpring Boot整合可以实现在应用程序中使用Elasticsearch进行数据的索引、搜索和分析。下面是一个简单的步骤来实现这个整合: 1. 添加依赖:在Spring Boot项目的pom.xml文件中,添加Elasticsearch相关的依赖。例如,可以使用spring-boot-starter-data-elasticsearch依赖来集成Elasticsearch。 2. 配置连接:在Spring Boot的配置文件中,配置Elasticsearch连接的相关信息,如主机地址、端口号、用户名和密码等。 3. 创建实体类:根据需要,创建要在Elasticsearch中索引的实体类。实体类一般使用注解来标识其在Elasticsearch中的索引和字段的映射关系。 4. 创建Repository:使用Spring Data Elasticsearch提供的@Repository注解来创建Elasticsearch的Repository接口。这个接口可以继承ElasticsearchRepository,并提供一些自定义的查询方法。 5. 编写业务逻辑:在Service层编写业务逻辑,调用自定义的Repository接口方法来对Elasticsearch进行操作。 6. 启动应用程序:使用Spring Boot的注解@SpringBootApplication来启动应用程序,其中会自动加载Elasticsearch的配置和相关的依赖。 通过以上步骤,我们就成功地将Elasticsearch整合到了Spring Boot应用程序中。可以通过访问RESTful接口来对Elasticsearch进行索引、搜索和分析等操作。此外,Spring Boot还提供了自动化配置和简化开发的特性,让整合过程更加方便快捷。 总结起来,通过整合ElasticsearchSpring Boot,我们可以利用Elasticsearch强大的搜索和存储功能来处理大量的数据,并结合Spring Boot框架的优势快速构建应用程序。 ### 回答3: Elasticsearch是一个基于Lucene的开源搜索和分析引擎,而Spring Boot是一个使用Java快速构建生产级别的应用程序的框架。将ElasticsearchSpring Boot整合可以提供强大的全文搜索和数据分析功能。 首先,我们需要在Spring Boot项目中添加Elasticsearch的依赖。可以通过在pom.xml文件中添加以下代码来实现: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 然后,我们需要创建一个Elasticsearch的配置类,用于配置Elasticsearch的连接信息。可以通过创建一个类,并添加`@Configuration`和`@EnableElasticsearchRepositories`注解来实现: ```java @Configuration @EnableElasticsearchRepositories(basePackages = "com.example.elasticsearch.repository") public class ElasticsearchConfig { @Value("${elasticsearch.host}") private String host; @Value("${elasticsearch.port}") private int port; @Bean public Client client() throws UnknownHostException { Settings settings = Settings.builder() .put("cluster.name", "elasticsearch").build(); TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), port)); return client; } @Bean public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException { return new ElasticsearchTemplate(client()); } } ``` 在上述代码中,我们通过从配置文件中读取主机和端口信息创建了一个Elasticsearch的客户端连接,并创建了一个用于Elasticsearch操作的ElasticsearchTemplate对象。 接下来,我们可以创建一个持久化层的接口,用于定义Elasticsearch的操作方法。可以通过创建一个接口,并添加`@Repository`注解来实现。例如: ```java @Repository public interface UserRepository extends ElasticsearchRepository<User, String> { List<User> findByName(String name); } ``` 在上述代码中,我们定义了一个UserRepository接口,继承了ElasticsearchRepository接口,并定义了一个按照名字查询用户的方法。 最后,我们可以在业务层或者控制层使用Elasticsearch相关的方法来进行搜索和分析操作。例如,我们可以在服务类中调用UserRepository的方法来实现用户的搜索: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> searchUser(String name) { return userRepository.findByName(name); } } ``` 通过以上步骤,我们就可以在Spring Boot项目中实现Elasticsearch整合和使用了。通过配置Elasticsearch连接信息、定义操作方法和调用相关方法,可以方便地实现全文搜索和数据分析的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Naijia_OvO

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

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

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

打赏作者

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

抵扣说明:

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

余额充值