最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot3集成ElasticSearch的方法詳解

 更新時(shí)間:2023年08月16日 09:05:09   作者:知了一笑  
Elasticsearch是一個(gè)分布式、RESTful風(fēng)格的搜索和數(shù)據(jù)分析引擎,適用于各種數(shù)據(jù)類型,數(shù)字、文本、地理位置、結(jié)構(gòu)化數(shù)據(jù)、非結(jié)構(gòu)化數(shù)據(jù),本文給大家詳解介紹了SpringBoot3集成ElasticSearch的方法,需要的朋友可以參考下

一、簡(jiǎn)介

Elasticsearch是一個(gè)分布式、RESTful風(fēng)格的搜索和數(shù)據(jù)分析引擎,適用于各種數(shù)據(jù)類型,數(shù)字、文本、地理位置、結(jié)構(gòu)化數(shù)據(jù)、非結(jié)構(gòu)化數(shù)據(jù);

在實(shí)際的工作中,歷經(jīng)過(guò)Elasticsearch從 6.0 7.0 的版本升級(jí),而這次SpringBoot3和ES8.0的集成,雖然腳本的語(yǔ)法變化很小,但是Java客戶端的API語(yǔ)法變化很大;

二、環(huán)境搭建

1、下載安裝包

需要注意的是,這些安裝包的版本要選擇對(duì)應(yīng)的,不然容易出問(wèn)題;

軟件包:elasticsearch-8.8.2-darwin-x86_64.tar.gz
分詞器工具:elasticsearch-analysis-ik-8.8.2.zip
可視化工具:kibana-8.8.2-darwin-x86_64.tar.gz

2、服務(wù)啟動(dòng)

不論是ES還是Kibana,在首次啟動(dòng)后,會(huì)初始化很多配置文件,可以根據(jù)自己的需要做相關(guān)的配置調(diào)整,比如常見(jiàn)的端口調(diào)整,資源占用,安全校驗(yàn)等;

1、啟動(dòng)ES
elasticsearch-8.8.2/bin/elasticsearch
本地訪問(wèn):localhost:9200
2、啟動(dòng)Kibana
kibana-8.8.2/bin/kibana
本地訪問(wèn):http://localhost:5601
# 3、查看安裝的插件
http://localhost:9200/_cat/plugins  ->  analysis-ik 8.8.2

三、工程搭建

1、工程結(jié)構(gòu)

2、依賴管理

starter-elasticsearch 組件中,實(shí)際上依賴的是 elasticsearch-java 組件的 8.7.1 版本;

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    <version>${spring-boot.version}</version>
</dependency>

3、配置文件

在上面環(huán)境搭建的過(guò)程中,已經(jīng)禁用了用戶和密碼的登錄驗(yàn)證,配置ES服務(wù)地址即可;

spring:
  # ElasticSearch配置
  elasticsearch:
    uris: localhost:9200

四、基礎(chǔ)用法

1、實(shí)體類

通過(guò) Document Field 注解描述ES索引結(jié)構(gòu)的實(shí)體類,注意這里 JsonIgnoreProperties 注解,解決索引中字段和實(shí)體類非一一對(duì)應(yīng)的而引起的JSON解析問(wèn)題;

@JsonIgnoreProperties(ignoreUnknown = true)
@Document(indexName = "contents_index", createIndex = false)
public class ContentsIndex implements Serializable {
    private static final long serialVersionUID=1L;
    @Field(type= FieldType.Integer)
    private Integer id;
    @Field(type= FieldType.Keyword)
    private String title;
    @Field(type= FieldType.Keyword)
    private String intro;
    @Field(type= FieldType.Text)
    private String content;
    @Field(type= FieldType.Integer)
    private Integer createId;
    @Field(type= FieldType.Keyword)
    private String createName;
    @Field(type= FieldType.Date,format = DateFormat.date_hour_minute_second)
    private Date createTime;
}

2、初始化索引

基于 ElasticsearchTemplate 類和上述實(shí)體類,實(shí)現(xiàn)索引結(jié)構(gòu)的初始化,并且將 tb_contents 表中的數(shù)據(jù)同步到索引中,最后通過(guò)ID查詢一條測(cè)試數(shù)據(jù);

@Service
public class ContentsIndexService {
    private static final Logger log = LoggerFactory.getLogger(ContentsIndexService.class);
    @Resource
    private ContentsService contentsService ;
    @Resource
    private ElasticsearchTemplate template ;
    /**
     * 初始化索引結(jié)構(gòu)和數(shù)據(jù)
     */
    public void initIndex (){
        // 處理索引結(jié)構(gòu)
        IndexOperations indexOps = template.indexOps(ContentsIndex.class);
        if (indexOps.exists()){
            boolean delFlag = indexOps.delete();
            log.info("contents_index exists,delete:{}",delFlag);
            indexOps.createMapping(ContentsIndex.class);
        } else {
            log.info("contents_index not exists");
            indexOps.createMapping(ContentsIndex.class);
        }
        // 同步數(shù)據(jù)庫(kù)表記錄
        List<Contents> contentsList = contentsService.queryAll();
        if (contentsList.size() > 0){
            List<ContentsIndex> contentsIndexList = new ArrayList<>() ;
            contentsList.forEach(contents -> {
                ContentsIndex contentsIndex = new ContentsIndex() ;
                BeanUtils.copyProperties(contents,contentsIndex);
                contentsIndexList.add(contentsIndex);
            });
            template.save(contentsIndexList);
        }
        // ID查詢
        ContentsIndex contentsIndex = template.get("10",ContentsIndex.class);
        log.info("contents-index-10:{}",contentsIndex);
    }
}

3、倉(cāng)儲(chǔ)接口

繼承 ElasticsearchRepository 接口,可以對(duì)ES這種特定類型的存儲(chǔ)庫(kù)進(jìn)行通用增刪改查操作;在測(cè)試類中對(duì)該接口的方法進(jìn)行測(cè)試;

// 1、接口定義
public interface ContentsIndexRepository extends ElasticsearchRepository<ContentsIndex,Long> {
}
// 2、接口測(cè)試
public class ContentsIndexRepositoryTest {
    @Autowired
    private ContentsIndexRepository contentsIndexRepository;
    @Test
    public void testAdd (){
        // 單個(gè)新增
        contentsIndexRepository.save(buildOne());
        // 批量新增
        contentsIndexRepository.saveAll(buildList()) ;
    }
    @Test
    public void testUpdate (){
        // 根據(jù)ID查詢后再更新
        Optional<ContentsIndex> contentsOpt = contentsIndexRepository.findById(14L);
        if (contentsOpt.isPresent()){
            ContentsIndex contentsId = contentsOpt.get();
            System.out.println("id=14:"+contentsId);
            contentsId.setContent("update-content");
            contentsId.setCreateTime(new Date());
            contentsIndexRepository.save(contentsId);
        }
    }
    @Test
    public void testQuery (){
        // 單個(gè)ID查詢
        Optional<ContentsIndex> contentsOpt = contentsIndexRepository.findById(1L);
        if (contentsOpt.isPresent()){
            ContentsIndex contentsId1 = contentsOpt.get();
            System.out.println("id=1:"+contentsId1);
        }
        // 批量ID查詢
        Iterator<ContentsIndex> contentsIterator = contentsIndexRepository
                                        .findAllById(Arrays.asList(10L,12L)).iterator();
        while (contentsIterator.hasNext()){
            ContentsIndex contentsIndex = contentsIterator.next();
            System.out.println("id="+contentsIndex.getId()+":"+contentsIndex);
        }
    }
    @Test
    public void testDelete (){
        contentsIndexRepository.deleteById(15L);
        contentsIndexRepository.deleteById(16L);
    }
}

4、查詢語(yǔ)法

無(wú)論是 ElasticsearchTemplate 類還是 ElasticsearchRepository 接口,都是對(duì)ES常用的簡(jiǎn)單功能進(jìn)行封裝,在實(shí)際使用時(shí),復(fù)雜的查詢語(yǔ)法還是依賴 ElasticsearchClient 和原生的API封裝;

這里主要演示七個(gè)查詢方法,主要涉及:ID查詢,字段匹配,組合與范圍查詢,分頁(yè)與排序,分組統(tǒng)計(jì),最大值查詢和模糊匹配;更多的查詢API還是要多看文檔中的案例才行;

public class ElasticsearchClientTest {
    @Autowired
    private ElasticsearchClient client ;
    @Test
    public void testSearch1 () throws IOException {
        // ID查詢
        GetResponse<ContentsIndex> resp = client.get(
                getReq ->getReq.index("contents_index").id("7"), ContentsIndex.class);
        if (resp.found()){
            ContentsIndex contentsIndex = resp.source() ;
            System.out.println("contentsIndex-7:"+contentsIndex);
        }
    }
    @Test
    public void testSearch2 () throws IOException {
        // 指定字段匹配
        SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index")
                        .query(query -> query.match(field -> field
                        .field("createName").query("張三"))),ContentsIndex.class);
        printResp(resp);
    }
    @Test
    public void testSearch3 () throws IOException {
        // 組合查詢:姓名和時(shí)間范圍
        Query byName = MatchQuery.of(field -> field.field("createName").query("王五"))._toQuery();
        Query byTime = RangeQuery.of(field -> field.field("createTime")
                        .gte(JsonData.of("2023-07-10T00:00:00"))
                        .lte(JsonData.of("2023-07-12T00:00:00")))._toQuery();
        SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index")
                        .query(query -> query.bool(boolQuery -> boolQuery.must(byName).must(byTime))),ContentsIndex.class);
        printResp(resp);
    }
    @Test
    public void testSearch4 () throws IOException {
        // 排序和分頁(yè),在14條數(shù)據(jù)中,根據(jù)ID倒序排列,從第5條往后取4條數(shù)據(jù)
        SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index")
                .from(5).size(4)
                .sort(sort -> sort.field(sortField -> sortField.field("id").order(SortOrder.Desc))),ContentsIndex.class);
        printResp(resp);
    }
    @Test
    public void testSearch5 () throws IOException {
        // 根據(jù)createId分組統(tǒng)計(jì)
        SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index")
                .aggregations("createIdGroup",agg -> agg.terms(term -> term.field("createId"))),ContentsIndex.class);
        Aggregate aggregate = resp.aggregations().get("createIdGroup");
        LongTermsAggregate termsAggregate = aggregate.lterms();
        Buckets<LongTermsBucket> buckets = termsAggregate.buckets();
        for (LongTermsBucket termsBucket : buckets.array()) {
            System.out.println(termsBucket.key() + " : " + termsBucket.docCount());
        }
    }
    @Test
    public void testSearch6 () throws IOException {
        // 查詢最大的ID
        SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index")
                .aggregations("maxId",agg -> agg.max(field -> field.field("id"))),ContentsIndex.class);
        for (Map.Entry<String, Aggregate> entry : resp.aggregations().entrySet()){
            System.out.println(entry.getKey()+":"+entry.getValue().max().value());
        }
    }
    @Test
    public void testSearch7 () throws IOException {
        // 模糊查詢title字段,允許1個(gè)誤差
        Query byContent = FuzzyQuery.of(field -> field.field("title").value("設(shè)計(jì)").fuzziness("1"))._toQuery();
        SearchResponse<ContentsIndex> resp = client.search(
                searchReq -> searchReq.index("contents_index").query(byContent),ContentsIndex.class);
        printResp(resp);
    }
    private void printResp (SearchResponse<ContentsIndex> resp){
        TotalHits total = resp.hits().total();
        System.out.println("total:"+total);
        List<Hit<ContentsIndex>> hits = resp.hits().hits();
        for (Hit<ContentsIndex> hit: hits) {
            ContentsIndex contentsIndex = hit.source();
            System.out.println(hit.id()+":"+contentsIndex);
        }
    }
}

五、參考源碼

文檔倉(cāng)庫(kù):
https://gitee.com/cicadasmile/butte-java-note
源碼倉(cāng)庫(kù):
https://gitee.com/cicadasmile/butte-spring-parent

文檔倉(cāng)庫(kù):https://gitee.com/cicadasmile/butte-java-note

以上就是SpringBoot3集成ElasticSearch的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot3集成ElasticSearch的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java調(diào)用SSE流式接口并流式返回給前端實(shí)現(xiàn)打字輸出效果

    Java調(diào)用SSE流式接口并流式返回給前端實(shí)現(xiàn)打字輸出效果

    在Web開(kāi)發(fā)中,有時(shí)我們需要將文件以流的形式返回給前端,下面這篇文章主要給大家介紹了關(guān)于Java調(diào)用SSE流式接口并流式返回給前端實(shí)現(xiàn)打字輸出效果的相關(guān)資料,需要的朋友可以參考下
    2024-08-08
  • Maven配置中repositories、distributionManagement、pluginRepositories用法及將已有jar包部署到私服

    Maven配置中repositories、distributionManagement、pluginRepositori

    這篇文章主要介紹了Maven配置中repositories、distributionManagement、pluginRepositories用法及將已有jar包部署到私服,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java線程安全中的單例模式

    Java線程安全中的單例模式

    這篇文章主要介紹了Java線程安全中的單例模式,需要的朋友可以參考下
    2015-02-02
  • Redis如何解決使用Session登錄帶來(lái)的共享問(wèn)題

    Redis如何解決使用Session登錄帶來(lái)的共享問(wèn)題

    文章首先介紹了Session的概念及其在實(shí)現(xiàn)登錄功能中的應(yīng)用,然后分析了Session共享問(wèn)題及其原因,并提出使用Redis作為替代方案解決這一問(wèn)題,接著,通過(guò)具體代碼示例展示了如何基于Session和Redis實(shí)現(xiàn)登錄功能,強(qiáng)調(diào)了Redis在解決Session共享問(wèn)題上的優(yōu)勢(shì)
    2026-04-04
  • eclipse老是自動(dòng)跳到console解決辦法

    eclipse老是自動(dòng)跳到console解決辦法

    eclipse啟動(dòng)服務(wù)后,想看一些properties信息或者別的,但老是自動(dòng)跳轉(zhuǎn)到console頁(yè)面,本文給大家介紹了解決辦法,對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • Java 并發(fā)編程ArrayBlockingQueue的實(shí)現(xiàn)

    Java 并發(fā)編程ArrayBlockingQueue的實(shí)現(xiàn)

    這篇文章主要介紹了Java 并發(fā)編程ArrayBlockingQueue的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù)

    詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù)

    本篇文章主要介紹了詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Java IO學(xué)習(xí)之緩沖輸入流(BufferedInputStream)

    Java IO學(xué)習(xí)之緩沖輸入流(BufferedInputStream)

    這篇文章主要介紹了Java IO學(xué)習(xí)之緩沖輸入流(BufferedInputStream)的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • java二叉樹(shù)面試題詳解

    java二叉樹(shù)面試題詳解

    下面小編就為大家?guī)?lái)一篇java二叉樹(shù)的幾道面試題詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-07-07
  • Netty序列化深入理解與使用

    Netty序列化深入理解與使用

    序列化 (Serialization)是將對(duì)象的狀態(tài)信息轉(zhuǎn)換為可以存儲(chǔ)或傳輸?shù)男问降倪^(guò)程。在序列化期間,對(duì)象將其當(dāng)前狀態(tài)寫入到臨時(shí)或持久性存儲(chǔ)區(qū)。以后,可以通過(guò)從存儲(chǔ)區(qū)中讀取或反序列化對(duì)象的狀態(tài),重新創(chuàng)建該對(duì)象
    2022-08-08

最新評(píng)論

江都市| 城固县| 彭州市| 永清县| 汝城县| 正定县| 南充市| 阳曲县| 南江县| 柳林县| 秭归县| 拉萨市| 昆山市| 山丹县| 正宁县| 农安县| 宜兰市| 华容县| 广州市| 仙居县| 绥滨县| 鸡东县| 马关县| 惠来县| 灵武市| 建湖县| 镇远县| 竹溪县| 凯里市| 基隆市| 文登市| 沧源| 蓬溪县| 高雄县| 梧州市| 白河县| 安丘市| 大关县| 大安市| 长葛市| 竹山县|