SpringBoot整合ES操作

发布于 2022-09-05  6.99k 次阅读


引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

配置客户端:

@Configuration
public class ESRestClientConfig extends AbstractElasticsearchConfiguration {

    @Value("${Elasticsearch.Host}")
    String host;

    public RestHighLevelClient elasticsearchClient() {

        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(host)
                .build();
        return RestClients.create(clientConfiguration).rest();

    }
}

ES默认提供了两个客户端对象:

  • ElasticSearchOperations:主要以对象进行ES操作
  • RestHighlevelClient(推荐):以Rest的风格进行交互

1.ElasticSearchOperations客户端操作

ElasticSearchOperations始终以对象方式操作ES

  • 索引:用来存放相似文档集合
  • 映射:用来决定放入文档的每个字段以什么样方式录入到ES中(字段类型 分词器)
  • 文档:可以被索引最小单元json数据格式
@Document(indexName = "products",createIndex = true)
public class Product {

    @Id
    private Integer id;

    @Field(type = FieldType.Keyword)
    private String title;

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

    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String description;
}

1,@Document:标注在类上代表一个对象为一个文档

  • indexName:创建索引的名称
  • createIndex:是否创建索引

2,@id:用于属性,将对象id字段与ES文档的_id对应

3,@Field:用于属性,用来描述属性在ES中存储类型以及分词情况……

  • type:指定字段类型
  • analyzer:指定分词器

例:测试保存一条文档

@SpringBootTest
class SpringbootEsApplicationTests {

   @Autowired
   ElasticsearchOperations elasticsearchOperations;

   @Test
   void contextLoads() {
      Product product = new Product();
      product.setId(1);
      product.setTitle("光影笔墨");
      product.setPrice(123.12);
      product.setDescription("留声机的回忆");
      elasticsearchOperations.save(product);
   }}

其他操作:

@Autowired
ElasticsearchOperations elasticsearchOperations;

//1,保存数据
@Test
void contextLoads() {
   Product product = new Product();
   product.setId(1);
   product.setTitle("光影笔墨");
   product.setPrice(123.12);
   product.setDescription("留声机的回忆");
   elasticsearchOperations.save(product);
}

//2,按照id查询文档
@Test
void selectId() {
   Product product = elasticsearchOperations.get("1", Product.class);
   System.out.println(product.getTitle()+"\n"+product.getDescription());
}

//3,按照id删除
@Test
void deleteId() {
   String delete = elasticsearchOperations.delete("1", Product.class);
   System.out.println(delete);
}

//4,查询所有文档
@Test
void selectAll() throws JsonProcessingException {
   SearchHits<Product> search = elasticsearchOperations.search(Query.findAll(), Product.class);
   System.out.println(search.getTotalHits());//总条数
   for (SearchHit<Product> pro:search){
      System.out.println(new ObjectMapper().writeValueAsString(pro.getContent()));
   }
}

2. RestHigLevelClient客户端

2.1 创建索引

@Autowired
RestHighLevelClient restHighLevelClient;

//创建索引
@Test
void Createindex() throws IOException {
    //创建索引对象,传入参数索引名
    CreateIndexRequest createIndexRequest = new CreateIndexRequest("index-wql");
    /**创建映射
     *1,参数1:映射内容
     *2,参数2:映射内容的格式
     * **/
    createIndexRequest.mapping("{\n" +
            "    \"properties\": {\n" +
            "      \"title\":{\n" +
            "        \"type\":\"text\"\n" +
            "      },\n" +
            "      \"price\":{\n" +
            "        \"type\": \"double\"\n" +
            "      },\n" +
            "      \"create_at\":{\n" +
            "        \"type\":\"date\"\n" +
            "      }\n" +
            "    }\n" +
            "  }", XContentType.JSON);
    //参数1:索引对象  参数2:请求的配置对象
    CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
    System.out.println(createIndexResponse.isAcknowledged());
    restHighLevelClient.close();
}

//删除索引
@Test
void DeleteIndex() throws IOException {

    //索引删除对象
    DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("pro");

    AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);

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

CreateIndexRequest:创建索引的对象

  • mapping():指定映射

restHighLevelClient.indices():索引的操作对象

2.2 文档操作

2.2.1 文档的创建

//创建文档
@Test
void indexDocment() throws IOException {
    //参数:索引名称
    IndexRequest indexRequest = new IndexRequest("index-wql");
    indexRequest.id("1")//指定文档id
                .source("{\n" + //指定文档数据
                        "  \"title\":\"英雄联盟手机壳\",\n" +
                        "  \"price\":20,\n" +
                        "  \"create_at\":\"2022-09-01\"\n" +
                        "}",XContentType.JSON);
    //创建文档
    IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    System.out.print(index.status());
}
  • IndexRequest:文档操作对象

2.2.2 更新文档

@Test
void updateDocment() throws IOException {

    //更新文档对象 参1:索引 参2:文档id
    UpdateRequest updateRequest = new UpdateRequest("index-wql","1");
    //更新的文档内容
    updateRequest.doc("{\n" +
            "  \"title\":\"我TM是个废物\",\n" +
            "  \"price\":\"0.1\",\n" +
            "  \"create_at\":\"2022-09-01\"\n" +
            "}",XContentType.JSON);

    UpdateResponse update = restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
    System.out.print(update.status());
}
  • UpdateRequest:更新文档对象

2.2.3 删除文档

//删除文档
@Test
void deleteDocment() throws IOException {

    //删除文档对象
    DeleteRequest deleteRequest = new DeleteRequest("index-wql","1000");

    DeleteResponse delete = restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);

    System.out.print(delete.status());
}
  • DeleteRequest:删除文档对象

2.2.4 基于ID查询文档

//基于id查询文档
@Test
void getDocment() throws IOException {
    //查询对象
    GetRequest getRequest = new GetRequest("index-wql","1");
    
    GetResponse documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
    
    System.out.print(documentFields.getSourceAsString()+"\n"+documentFields.getId());
}
  • GetRequest:查询对象

2.3 文档查询操作

1,查询所有文档

@Autowired
RestHighLevelClient restHighLevelClient;

@Test
void QueryAll() throws IOException {
    //创建搜索对象 参数:指定索引
    SearchRequest searchRequest = new SearchRequest("index-wql");
    //创建查询条件对象
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.matchAllQuery());//查询所有
    searchRequest.source(searchSourceBuilder);

    SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

    //获取结果
    SearchHit[] hits = search.getHits().getHits();
    for (SearchHit h:hits){
        System.out.println(h.getId()+"\t"+h.getSourceAsString());
    }
  • SearchRequest:条件查询对象
  • SearchSourceBuilder:条件约束对象

它的API跟Kibana的返回json是一样的,用对象的方式调用json结果

2,关键字查询

//关键字查询
@Test
void QueryTerm() throws IOException {

    SearchRequest searchRequest = new SearchRequest("index-wql");

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.termQuery("title","废"));
    searchRequest.source(searchSourceBuilder);

    SearchResponse search = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
    SearchHit[] hits = search.getHits().getHits();
    for (SearchHit h:hits){
        System.out.println(h.getId()+"\t"+h.getSourceAsString());
    }
  • QueryBuilders.termQuery():关键字查询方法 (参1:字段,参2:值)

3,范围查询

@Test
void QueryRange() throws IOException {

    SearchRequest searchRequest = new SearchRequest("index-wql");

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.rangeQuery("price").lt(50));
    searchRequest.source(searchSourceBuilder);

    SearchResponse search = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
    SearchHit[] hits = search.getHits().getHits();
    for (SearchHit h:hits){
        System.out.println(h.getId()+"\t"+h.getSourceAsString());
    }
}
  • QueryBuilders.rangeQuery:范围查询方法

其他查询格式都是一样的唯一变的是QueryBuilders方法:

  • 前缀查询:QueryBuilders.prefixQuery()
  • 通配符查询:QueryBuilders.wildcardQuery()
  • 多ID查询:QueryBuilders.idsQuery().addIds();
  • 多字段查询:QueryBuilders.multiMatchQuery("值","字段……","")

4,分页高亮排序查询

//分页排序查询
@Test
void QueryPageSort() throws IOException {

    SearchRequest searchRequest = new SearchRequest("index-wql");

    //创建一个高亮器
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    /**
     * field():需要高亮的字段
     * requireFieldMatch():关闭字段匹配
     * preTags():自定义高亮标签前缀
     * postTags():标签后缀
     */
    highlightBuilder.requireFieldMatch(false).field("title").preTags("<span style='color:red'>").postTags("</span>");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.termQuery("title","废"))
                        .from(0)//起始位置
                        .size(10)//每页条数
                        .sort("price", SortOrder.DESC)//排序字段
                        .fetchSource(new String[]{},new String[]{"create_at"})//数组1:结果需要包含的字段 数组2:结果需要排除的字段
                        .highlighter(highlightBuilder);//指定高亮
    searchRequest.source(searchSourceBuilder);
    SearchResponse search = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
    SearchHit[] hits = search.getHits().getHits();
    for (SearchHit h:hits){
        System.out.println(h.getId()+"\t"+h.getSourceAsString());


        Map<String, HighlightField> highlightFields = h.getHighlightFields();
        if(highlightFields.containsKey("title")){
            System.out.print("title高亮结果"+highlightFields.get("title").fragments()[0]);
        }
    }
}
  • from():起始位置
  • size():单页条数
  • sort():排序,指定排序字段(可选项排序规则)
  • ……

5,过滤查询

  • query:查询精确,查询计算文档得分,并根据得分进行返回
  • filter query:过滤查询,用来在大量数据中筛选出本地查询相关数据,不会计算文档得分,经常使用filter query的结果会进行缓存

注:一旦使用query和filterQuery,es优先执行filter Query然后再执行Query

@Test
void QueryFilter() throws IOException {

    SearchRequest searchRequest = new SearchRequest("index-wql");

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.matchAllQuery())
                      //指定过滤条件
                       .postFilter(QueryBuilders.termQuery("title","物"));
    searchRequest.source(searchSourceBuilder);
    SearchResponse search = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
    SearchHit[] hits = search.getHits().getHits();
    for (SearchHit h:hits){
        System.out.println(h.getId()+"\t"+h.getSourceAsString());
    }
}
  • postFilter:指定过滤条件

路漫漫其修远兮,吾将上下而求索