1. 程式人生 > 其它 >一個基於ElasticSearchRestTemplate的增刪改查的例子

一個基於ElasticSearchRestTemplate的增刪改查的例子

現在網上的用springboot對ElasticSearch做增刪改查的文章,幾乎都是用的原生API或者繼承了ElasticsearchRepository去做。但是現在我用的springboot2.5.6已經移除了ElasticsearchRepository裡的search()方法,只剩了一些特別基礎的增刪改查,基本上是不能用的。官方明顯是想讓開發者用ElasticsearchRestTemplate去做,但是搜尋網上沒有發現很好的增刪改查教程,於是我把自己寫的程式碼貼一下:

package com.markerhub.search.model.mq;

import com.alibaba.fastjson.JSON;
import com.markerhub.config.RabbitConfig;
import com.markerhub.entity.Blog;
import com.markerhub.search.model.BlogPostDocument;
import com.markerhub.service.BlogService;
import com.markerhub.util.MyUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@RabbitListener(queues = RabbitConfig.ES_QUEUE)
public class MQMessageHandler {

    BlogService blogService;

    @Autowired
    public void setBlogService(BlogService blogService) {
        this.blogService = blogService;
    }

    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    public void setElasticsearchRestTemplate(ElasticsearchRestTemplate elasticsearchRestTemplate) {
        this.elasticsearchRestTemplate = elasticsearchRestTemplate;
    }

    @SneakyThrows
    @RabbitHandler
    public void handler(PostMQIndexMessage message) {
        switch (message.getType()) {
            case PostMQIndexMessage.UPDATE:

                Long updateId = message.getPostId();
                Blog blogExisted = blogService.getById(updateId);
                BlogPostDocument postDocument = MyUtils.blogToDocument(blogExisted);
                String obj = JSON.toJSONString(postDocument);
                Document document = Document.parse(obj);

                UpdateQuery query = UpdateQuery
                        .builder(String.valueOf(updateId))
                        .withDocument(document)
                        .build();

                IndexCoordinates indexCoordinates = elasticsearchRestTemplate.getIndexCoordinatesFor(BlogPostDocument.class);

                UpdateResponse update = elasticsearchRestTemplate.update(query, indexCoordinates);

                String result = String.valueOf(update.getResult());
                log.info("更新結果: {}", result);
                break;
            case PostMQIndexMessage.REMOVE:

                Long deleteId = message.getPostId();

                String delete = elasticsearchRestTemplate.delete(deleteId.toString(), BlogPostDocument.class);

                log.info("刪除結果: {}", delete);

                break;
            case PostMQIndexMessage.CREATE:

                Long createId = message.getPostId();
                Blog newBlog = blogService.getById(createId);

                BlogPostDocument newDocument = MyUtils.blogToDocument(newBlog);

                BlogPostDocument save = elasticsearchRestTemplate.save(newDocument);
                log.info("儲存結果: {}", save);
                break;
            default:
                log.error("沒找到對應的訊息型別: {}", message);
        }
    }
}

上面是對rabbitmq整合時當資料庫更新,往佇列發一條訊息,發訊息的程式碼沒有貼出來,不過重點不在這裡。這裡通知消費者去執行相關的方法。首先ElasticsearchRestTemplate把增刪改查分開了,增是增,刪是刪,改是改,查是查,不能再把增改一起用了。實現比較簡單,程式碼也比較直白,查詢程式碼是這樣的:

/**
     * 搜尋功能,從es搜尋
     */
    @GetMapping("/search/{currentPage}")
    public Result search(@PathVariable Integer currentPage, @RequestParam String keyword) {
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, "title", "description", "content");
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(multiMatchQueryBuilder)
                .withSort(SortBuilders.fieldSort("created").order(SortOrder.DESC))
                .build();

        SearchHits<BlogPostDocument> search = elasticsearchRestTemplate.search(nativeSearchQuery, BlogPostDocument.class);

        if (search.getTotalHits() == 0) {
            throw new ResourceNotFoundException("沒有相關記錄");
        }

//        List<SearchHit<BlogPostDocument>> list = search.getSearchHits();

        ArrayList<BlogPostDocument> list = new ArrayList<>();

        for (SearchHit<BlogPostDocument> hit : search.getSearchHits()) {
            list.add(hit.getContent());
        }

        Page<BlogPostDocument> page = MyUtils.listToPage(list, currentPage, 5);

        return Result.succ(page);
    }


    @GetMapping("/searchByYear/{currentPage}/{year}")
    public Result searchByYear(@PathVariable Integer currentPage, @RequestParam String keyword, @PathVariable Integer year) {

        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, "title", "description", "content");

        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.rangeQuery("created").gte(year + "-01-01T00:00:00").lte(year + "-12-31T23:59:59")
                                .includeUpper(true)
                                .includeLower(true))
                        .must(multiMatchQueryBuilder))
                .withSort(SortBuilders.fieldSort("created").order(SortOrder.DESC))
                .build();

        SearchHits<BlogPostDocument> search = elasticsearchRestTemplate.search(nativeSearchQuery, BlogPostDocument.class);

        if (search.getTotalHits() == 0) {
            throw new ResourceNotFoundException("沒有相關記錄");
        }

        ArrayList<BlogPostDocument> list = new ArrayList<>();

        for (SearchHit<BlogPostDocument> hit : search.getSearchHits()) {
            list.add(hit.getContent());
        }

        Page<BlogPostDocument> page = MyUtils.listToPage(list, currentPage, 5);

        return Result.succ(page);
    }

總體來看,ElasticsearchRestTemplate的應用方法是,先構建相應的query物件(MultiMatchQueryBuilder或者UpdateQuery之類的),在這個物件裡傳入你的查詢條件或者修改的物件或者新增的物件,再傳入ElasticsearchRestTemplate的相關方法裡。

本文來自部落格園,作者:imissinstagram,轉載請註明原文連結:https://www.cnblogs.com/LostSecretGarden/p/15685055.html