欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot整合ES-Elasticsearch的實(shí)例

 更新時(shí)間:2022年05月05日 10:35:13   作者:融極  
這篇文章主要介紹了SpringBoot整合ES-Elasticsearch的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

概述

本文介紹 Spring Boot 項(xiàng)目中整合 ElasticSearch 并實(shí)現(xiàn) CRUD 操作,包括分頁、滾動(dòng)等功能。

添加Maven依賴

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

配置application.yml

spring:
? elasticsearch:
? ? rest:
? ? ? uris: 192.168.1.81:9200

創(chuàng)建索引對(duì)象

package com.practice.elkstudy.entity;
import cn.hutool.core.date.DateTime;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import java.util.Date;
/**
?* @Description : 文檔模型
?* @Version : V1.0.0
?* @Date : 2021/12/22 14:08
?*/
@Document(indexName = "article")
@Data
public class ArticleEntity {
? ? @Id
? ? private String id;
? ? private String title;
? ? private String content;
? ? private Integer userId;
? ? private Date createTime = DateTime.now();
}

SpringBoot操作ES數(shù)據(jù)的三種方式

  • 實(shí)現(xiàn)ElasticsearchRepository接口
  • 引入ElasticsearchRestTemplate
  • 引入ElasticsearchOperations

實(shí)現(xiàn)索引對(duì)應(yīng)的Repository

package com.practice.elkstudy.repository;
import com.practice.elkstudy.entity.ArticleEntity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
?* @Description : article數(shù)據(jù)操作接口
?* @Version : V1.0.0
?* @Date : 2021/12/22 14:18
?*/
public interface ArticleRepository extends ElasticsearchRepository<ArticleEntity,String> {
}

文檔操作

下面可以使用這個(gè) ArticleRepository 來操作 ES 中的 Article 數(shù)據(jù)。

我們這里沒有手動(dòng)創(chuàng)建這個(gè) Article 對(duì)應(yīng)的索引,由 elasticsearch 默認(rèn)生成。

下面的接口,實(shí)現(xiàn)了 spring boot 中對(duì) es 數(shù)據(jù)進(jìn)行插入、更新、分頁查詢、滾動(dòng)查詢、刪除等操作??梢宰鳛橐粋€(gè)參考。

其中,使用了 Repository 來獲取、保存、刪除 ES 數(shù)據(jù);使用 ElasticsearchRestTemplate 或 ElasticsearchOperations 來進(jìn)行分頁/滾動(dòng)查詢。

文檔保存、查詢、刪除

package com.practice.elkstudy.controller.controller;
import com.practice.elkstudy.entity.ArticleEntity;
import com.practice.elkstudy.repository.ArticleRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Optional;
/**
 * @Description : article控制類
 * @Version : V1.0.0
 * @Date : 2021/12/22 14:11
 */
@RestController
@RequestMapping("/elk")
public class ArticleController {
    @Resource
    private ArticleRepository articleRepository;
    /**
     * 根據(jù)文檔id查詢數(shù)據(jù)
     *
     * @param id 文檔id
     * @return 文檔詳情
     */
    @GetMapping("/byId")
    public String findById(@RequestParam String id) {
        Optional<ArticleEntity> record = articleRepository.findById(id);
        return  record.toString();
    }
    /**
     * 保存文檔信息
     *
     * @param article 文檔詳情
     * @return 保存的文檔信息
     */
    @PostMapping("/saveArticle")
    public String saveArticle(@RequestBody ArticleEntity article) {
        ArticleEntity result = articleRepository.save(article);
        return result.toString();
    }
	@DeleteMapping("/deleteById")
    public String deleteArticle(@RequestParam String id) {
        articleRepository.deleteById(id);
        return "success";
    }
}

分頁查詢與滾動(dòng)查詢

package com.practice.elkstudy.controller.controller;
import com.practice.elkstudy.entity.ArticleEntity;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.SearchHitsImpl;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * @Description : article高級(jí)查詢
 * @Version : V1.0.0
 * @Date : 2021/12/22 15:10
 */
@RestController
@RequestMapping("/elk")
public class ArticleAdvanceController {
    @Autowired
    private ElasticsearchRestTemplate restTemplate;
    @Autowired
    private ElasticsearchOperations operations;
    /**
     * 分頁查詢
     *
     * @param pageNum  頁碼,從0開始
     * @param pageSize 分頁大小
     * @return 查詢結(jié)果
     */
    @GetMapping("/queryPage")
    public String queryPage(@RequestParam int pageNum, @RequestParam int pageSize) {
        NativeSearchQuery query = new NativeSearchQuery(new BoolQueryBuilder());
        query.setPageable(PageRequest.of(pageNum, pageSize));
        // 方法1
        SearchHits<ArticleEntity> search = restTemplate.search(query, ArticleEntity.class);
        // 方法2
        // SearchHits<ArticleEntity> search = operations.search(query, ArticleEntity.class);
        List<ArticleEntity> articles = search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
        return articles.toString();
    }
    /**
     * 滾動(dòng)查詢
     *
     * @param scrollId 滾動(dòng)id
     * @param pageSize 分頁大小
     * @return 查詢結(jié)果
     */
    @GetMapping(value = "/scrollQuery")
    public String scroll(String scrollId, Integer pageSize) {
        if (pageSize == null || pageSize <= 0) {
            return "please input query page num";
        }
        NativeSearchQuery query = new NativeSearchQuery(new BoolQueryBuilder());
        query.setPageable(PageRequest.of(0, pageSize));
        SearchHits<ArticleEntity> searchHits;
        if (StringUtils.isEmpty(scrollId) || scrollId.equals("0")) {
            // 開啟一個(gè)滾動(dòng)查詢,設(shè)置該scroll上下文存在60s
            // 同一個(gè)scroll上下文,只需要設(shè)置一次query(查詢條件)
            searchHits = restTemplate.searchScrollStart(60000, query, ArticleEntity.class, IndexCoordinates.of("article"));
            if (searchHits instanceof SearchHitsImpl) {
                scrollId = ((SearchHitsImpl) searchHits).getScrollId();
            }
        } else {
            // 繼續(xù)滾動(dòng)
            searchHits = restTemplate.searchScrollContinue(scrollId, 60000, ArticleEntity.class, IndexCoordinates.of("article"));
        }
        List<ArticleEntity> articles = searchHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
        if (articles.size() == 0) {
            // 結(jié)束滾動(dòng)
            restTemplate.searchScrollClear(Collections.singletonList(scrollId));
            scrollId = null;
        }
        if (Objects.isNull(scrollId)) {
            Map<String, String> result = new HashMap<>(2);
            result.put("articles", articles.toString());
            result.put("message", "已到末尾");
            return result.toString();
        } else {
            Map<String, String> result = new HashMap<>();
            result.put("count", String.valueOf(searchHits.getTotalHits()));
            result.put("pageSize", String.valueOf(articles.size()));
            result.put("articles", articles.toString());
            result.put("scrollId", scrollId);
            return result.toString();
        }
    }
}

ES深度分頁 vs 滾動(dòng)查詢

之前遇到的一個(gè)問題,日志檢索的接口太慢了。

開始使用的是深度分頁,即1,2,3…10,這樣的分頁查詢,查詢條件較多(十多個(gè)參數(shù))、查詢數(shù)據(jù)量較大(單個(gè)日志索引約2億條數(shù)據(jù))。

分頁查詢速度慢的原因在于:ES的分頁查詢,如查詢第100頁數(shù)據(jù),每頁10條,是先從每個(gè)分區(qū)(shard,一個(gè)索引默認(rèn)是5個(gè)shard)中把命中的前100*10條數(shù)據(jù)查出來,然后協(xié)調(diào)節(jié)點(diǎn)進(jìn)行合并操作,最后給出100頁的數(shù)據(jù)。也就是說,實(shí)際被加載到內(nèi)存的數(shù)據(jù)遠(yuǎn)遠(yuǎn)超過理想情況。

這樣,索引分片數(shù)越多,查詢頁數(shù)越多,查詢速度就越慢。ES默認(rèn)的max_result_window是10000條,也就是正常情況下,用分頁查詢到10000條數(shù)據(jù)時(shí),就不會(huì)在返回下一頁數(shù)據(jù)了。

如果不需要進(jìn)行跳頁,比如直接查詢第100頁數(shù)據(jù),或者數(shù)據(jù)量非常大,那么可以考慮用scroll查詢。在scroll查詢下,第1次需要根據(jù)查詢參數(shù)開啟一個(gè)scroll上下文,設(shè)置上下文緩存時(shí)間。以后的滾動(dòng)只需要根據(jù)第一次返回的scrollId來進(jìn)行即可。

scroll只支持往下滾動(dòng),如果想要往前滾動(dòng),還可以根據(jù)scrollId緩存查詢結(jié)果,這樣就可以實(shí)現(xiàn)上下文滾動(dòng)查詢了一一就像大家經(jīng)常使用的淘寶商品檢索時(shí)上下滾動(dòng)一樣。 

SpringBoot集成ES基本使用

#配置es
#Liunx 上的ip地址和配置端口號(hào)
spring.elasticsearch.rest.uris=192.168.113.129:9200

在test中測(cè)試

import com.alibaba.fastjson.JSON;
import com.hzx.pojo.User;
import com.hzx.utils.ESconst;
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.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
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.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.concurrent.TimeUnit;
@Autowired
private RestHighLevelClient client;
@Test
void contextLoads() throws IOException {
    //創(chuàng)建索引請(qǐng)求
    CreateIndexRequest request = new CreateIndexRequest("hong_index");
    //客戶端執(zhí)行請(qǐng)求 IndicesClient  create創(chuàng)建請(qǐng)求  RequestOptions.DEFAULT默認(rèn)請(qǐng)求參數(shù)
    CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
    //獲取返回的參數(shù)
    System.out.println(createIndexResponse);
}
@Test
void test2() throws IOException {
    //獲取指定索引庫
    GetIndexRequest request = new GetIndexRequest("hong_index2");
    //判斷獲取索引是否存在
    boolean exists = client.indices().exists(request,RequestOptions.DEFAULT);
    //如果索引存在就返回為true  或者 為false
    System.out.println(exists);
}
@Test
void test3() throws IOException {
    //刪除指定索引庫
    DeleteIndexRequest request = new DeleteIndexRequest("hong_index");
    //獲取刪除索引
    AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
    //檢查索引是否被刪除
    System.out.println(delete.isAcknowledged());
}
    //測(cè)試添加文檔
    @Test
    void test4() throws IOException {
        //創(chuàng)建對(duì)象
        User user = new User("棗信",18);
        //創(chuàng)建索引庫
        IndexRequest request = new IndexRequest("hong_index");
        //規(guī)則 為 put /hong_index/_doc/1
        //創(chuàng)建的id
        request.id("1");
        //創(chuàng)建的時(shí)間
        request.timeout(TimeValue.timeValueSeconds(1));
//        request.timeout("1s");
        //將數(shù)據(jù)放入到請(qǐng)求     JSON.toJSONString(user)將對(duì)象轉(zhuǎn)換為json
        request.source(JSON.toJSONString(user), XContentType.JSON);
        //客戶端發(fā)送請(qǐng)求   向索引中添加數(shù)據(jù)
        IndexResponse indices = client.index(request, RequestOptions.DEFAULT);
        //獲取返回的json對(duì)象
        System.out.println(indices.toString());
        //獲取發(fā)送請(qǐng)求的狀態(tài) 添加為CREATED  更新為OK
        System.out.println(indices.status());
    }
//獲取文檔信息
@Test
void test6() throws IOException {
    //根據(jù)索引傳入的id獲取
    GetRequest getRequest = new GetRequest("hong_index","1");
    //通過get獲取信息
    GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
    //根據(jù)指定的Source獲取對(duì)應(yīng)內(nèi)容
    System.out.println(getResponse.getSourceAsString());
    //打印json對(duì)象
    System.out.println(getResponse);
}
//更新 修改信息
@Test
void test7() throws IOException {
    //根據(jù)索引庫傳入的id更新
    UpdateRequest updateRequest = new UpdateRequest("hong_index","1");
    //更新時(shí)間
    updateRequest.timeout("1s");
    //創(chuàng)建對(duì)象
    User user = new User("李四", 26);
    //更新    將對(duì)象轉(zhuǎn)換為json
    updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);
    //客戶端發(fā)送請(qǐng)求,進(jìn)行更新
    UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
    //獲取更新狀態(tài)
    System.out.println(update.status());
}
//刪除文檔信息
@Test
void test8() throws IOException {
    //根據(jù)傳入的索引id進(jìn)行刪除
    DeleteRequest request = new DeleteRequest("hong_index","1");
    //發(fā)送請(qǐng)求,刪除
    DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
    //獲取刪除的狀態(tài)   沒有刪除成功為NOT_FOUND 刪除成功為OK
    System.out.println(delete.status());
}
//批量添加數(shù)據(jù)
@Test
void test9() throws IOException {
    //創(chuàng)建批量添加
    BulkRequest bulkRequest = new BulkRequest();
    //添加時(shí)間
    bulkRequest.timeout("8s");
    //創(chuàng)建一個(gè)arraylist集合
    ArrayList<User> userList = new ArrayList<>();
    userList.add(new User("李四",19));
    userList.add(new User("王五",25));
    userList.add(new User("趙剛",30));
    userList.add(new User("張三",21));
    userList.add(new User("趙六",36));
    userList.add(new User("小武",20));
    //批量處理請(qǐng)求
    for (int i = 0; i < userList.size(); i++) {
        //批量更新和刪除 在這修改對(duì)應(yīng)的請(qǐng)求即可       不添加id(""+(i+1)) 會(huì)默認(rèn)隨機(jī)id,在大數(shù)據(jù)情況下,讓他默認(rèn)隨機(jī)id
        bulkRequest.add(new IndexRequest("hong_index").id(""+(i+1)).source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
    }
    //批量添加發(fā)送請(qǐng)求
    BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
    //獲取批量添加的狀態(tài) 返回false代表添加成功
    System.out.println(bulk.hasFailures());
}
//查詢索引信息
@Test
void test10() throws IOException {
    //查詢
    SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
    //構(gòu)建搜索條件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //查詢條件,可以使用QueryBuilders工具來實(shí)現(xiàn)
    // QueryBuilders.termQuery精確查詢
    // QueryBuilders.matchQuery()查詢所有
    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "李四");
    //查詢的時(shí)間
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
    //將查詢的sourceBuilder放入searchRequest中
    searchRequest.source(sourceBuilder);
    //發(fā)送請(qǐng)求
    SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
    //獲取信息
    System.out.println(JSON.toJSONString(search.getHits()));
    //循環(huán)變量出信息
    for(SearchHit documentFields : search.getHits().getHits()){
        //獲取所有信息
        System.out.println(documentFields.getSourceAsMap());
    }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • Spring?Security?中多個(gè)身份驗(yàn)證的示例代碼

    Spring?Security?中多個(gè)身份驗(yàn)證的示例代碼

    這篇文章主要介紹了Spring?Security?中多個(gè)身份驗(yàn)證的示例代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • springboot使用ThreadPoolTaskExecutor多線程批量插入百萬級(jí)數(shù)據(jù)的實(shí)現(xiàn)方法

    springboot使用ThreadPoolTaskExecutor多線程批量插入百萬級(jí)數(shù)據(jù)的實(shí)現(xiàn)方法

    這篇文章主要介紹了springboot利用ThreadPoolTaskExecutor多線程批量插入百萬級(jí)數(shù)據(jù),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • Java動(dòng)態(tài)代理四種實(shí)現(xiàn)方式詳解

    Java動(dòng)態(tài)代理四種實(shí)現(xiàn)方式詳解

    這篇文章主要介紹了Java四種動(dòng)態(tài)代理實(shí)現(xiàn)方式,對(duì)于開始學(xué)習(xí)java動(dòng)態(tài)代理或者要復(fù)習(xí)java動(dòng)態(tài)代理的朋友來講很有參考價(jià)值,有感興趣的朋友可以參考一下
    2021-04-04
  • JAVA線程同步實(shí)例教程

    JAVA線程同步實(shí)例教程

    這篇文章主要介紹了JAVA線程同步實(shí)例教程,在Java程序設(shè)計(jì)中有著非常廣泛的應(yīng)用,需要的朋友可以參考下
    2014-08-08
  • win10安裝JDK14.0.2的詳細(xì)安裝過程

    win10安裝JDK14.0.2的詳細(xì)安裝過程

    這篇文章主要介紹了win10安裝JDK14.0.2的詳細(xì)安裝過程的相關(guān)資料,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Springboot實(shí)現(xiàn)自定義錯(cuò)誤頁面的方法(錯(cuò)誤處理機(jī)制)

    Springboot實(shí)現(xiàn)自定義錯(cuò)誤頁面的方法(錯(cuò)誤處理機(jī)制)

    這篇文章主要介紹了Springboot實(shí)現(xiàn)自定義錯(cuò)誤頁面的方法(錯(cuò)誤處理機(jī)制),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • maven項(xiàng)目在svn中的上傳與檢出的方法

    maven項(xiàng)目在svn中的上傳與檢出的方法

    企業(yè)開發(fā)中經(jīng)常使用svn來為我們控制代碼版本,也經(jīng)常使用maven來管理項(xiàng)目。下面將介紹一下如何將maven項(xiàng)目上傳到svn中,如何將項(xiàng)目從svn中檢出,感興趣的小伙伴們可以參考一下
    2019-02-02
  • springboot常用注釋的講解

    springboot常用注釋的講解

    今天小編就為大家分享一篇關(guān)于springboot常用注釋的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Java中的ThreadLocalMap源碼解讀

    Java中的ThreadLocalMap源碼解讀

    這篇文章主要介紹了Java中的ThreadLocalMap源碼解讀,ThreadLocalMap是ThreadLocal的內(nèi)部類,是一個(gè)key-value數(shù)據(jù)形式結(jié)構(gòu),也是ThreadLocal的核心,需要的朋友可以參考下
    2023-09-09
  • Java發(fā)送form-data請(qǐng)求的實(shí)例代碼

    Java發(fā)送form-data請(qǐng)求的實(shí)例代碼

    在Java中發(fā)送form-data請(qǐng)求,可以使用Apache?HttpClient或OkHttp這樣的HTTP客戶端庫來發(fā)送請(qǐng)求,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-10-10

最新評(píng)論