spirngboot集成elasticsearch

这篇文章同样可以在我自搭的小博客里看到:https://spzgczyj.top/blog/article.html?articleId=310

准备环节

第一步:在pom.xml中引入elasticsearch的依赖


     org.elasticsearch.client
     transport
     ${elasticsearch.version}




     org.apache.logging.log4j
     log4j-core
     2.7

第二步:覆盖springboot给我们提供的默认版本的es,我这里用的es是6.3.2,所以这里的es版本我指定成6.3.2


   UTF-8
   UTF-8
   1.8
   
   6.3.2
   

第三步:编写配置类:

package com.gkd.blog.config;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @author :zhaoyijie(Aquarius_genius)水瓶座鬼才
 * @create :2020/1/25 13:01
 * @Email   : [email protected]
 */
@Configuration
public class ESConfig {
    @Bean
    public TransportClient client() throws UnknownHostException {
        TransportAddress node=new TransportAddress(InetAddress.getByName("localhost"),9300);
        //集群名blog
        Settings settings = Settings.builder().put("cluster.name","blog").build();
        TransportClient client=new PreBuiltTransportClient(settings);
        //这里可以addTransportAddress(node)多个节点
        client.addTransportAddress(node);
        System.out.println(client);
        return client;
    }
}

说明:不同版本的可能会不同:5.5.2版本用InetSocketTransportAddress,6.3.2版本用TransportAddress。这里端口用9300,ES Rest API端口9200,项目需要用tcp协议去和es通信 ,ES默认tcp端口9300,默认cluster-name my-application。这里要特别说明,实际开发不是这样子写的,因为这样子写配置文件需要改es的yml文件,详情看我的另外一篇文章:elasticsearch报错解决办法:NoNodeAvailableException[None of the configured nodes are available。但是我们只是简单实现,简单写也是可以的,因为我们的目的就一个,快速查询出匹配的文章就行了,我这里做的是快速查询出匹配的文章。

 

第四步:编写实体类

package com.gkd.blog.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.lang.NonNull;

import java.util.Date;

/**
 * @author :zhaoyijie(Aquarius_genius)水瓶座鬼才
 * @create :2020/1/5 15:12
 * @Email   : [email protected]
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Article {
    private Integer id;//文章id
    @NonNull
    private String title;//文章标题
    @NonNull
    private String content;//文章内容
    @NonNull
    private String articleClassify;//文章类别
    //写成long时间戳,避免ios里的js日期格式不兼容的情况发生
    @JsonFormat(shape = JsonFormat.Shape.NUMBER)
    private Date addTime;//文章加入时间
    private Integer viewCount;//文章浏览量
    private Integer sumComment;//总评论
    private Integer supportCount;//总点赞数
}

第五步:编写控制器类

package com.gkd.blog.controller;

import com.gkd.blog.util.EsUtils;
import org.elasticsearch.client.transport.TransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author :zhaoyijie(Aquarius_genius)水瓶座鬼才
 * @create :2020/1/25 13:27
 * @Email   : [email protected]
 * @Description :
 */
@RestController
public class elasticsearchController {
    @Autowired
    TransportClient client;

    /**
    * @Description: 跟据关键字查找符合条件的数据,只跟文章标题,内容,文章分类比较
    * @Param: [keyword] 查询关键字
    * @return: org.springframework.http.ResponseEntity
    */
    @PostMapping("query/blog/article")
    @ResponseBody
    public ResponseEntity query(@RequestParam(name = "keyword") String keyword){
        StopWatch watch=new StopWatch();
        watch.start();
        Map map=new HashMap<>();
        List> result = EsUtils.queryShould(keyword, this.client);
        watch.stop();
        map.put("TotalTimeMillis",watch.getTotalTimeMillis());
        map.put("result",result);
        return new ResponseEntity(map, HttpStatus.OK);
    }

}

第六步:编写ESutils类

package com.gkd.blog.util;

import com.gkd.blog.entity.Article;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;

import java.io.IOException;
import java.util.*;

/**
 * @author :zhaoyijie(Aquarius_genius)水瓶座鬼才
 * @create :2020/1/25 14:34
 * @Email   : [email protected]
 * @Description :
 */
public class EsUtils {

    public static List> queryMust(Article article, TransportClient client) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //must想当于and should相当于or
        boolQuery.must(QueryBuilders.matchQuery("title", article.getTitle()));
        boolQuery.must(QueryBuilders.matchQuery("content", article.getContent()));
        boolQuery.must(QueryBuilders.matchQuery("articleClassify", article.getArticleClassify()));
        SearchRequestBuilder builder = client.prepareSearch("blog").
                setTypes("article").
                setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(boolQuery);
        //System.out.println(builder);
        SearchResponse searchResponse = builder.get();
        List> result = new ArrayList>();

        for (SearchHit hit : searchResponse.getHits()) {
            result.add(hit.getSourceAsMap());
        }
        return result;
    }

    public static List> queryShould(String keyword, TransportClient client) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //must想当于and should相当于or
        boolQuery.should(QueryBuilders.matchQuery("title", keyword));
        boolQuery.should(QueryBuilders.matchQuery("content", keyword));
        boolQuery.should(QueryBuilders.matchQuery("articleClassify", keyword));
        SearchRequestBuilder builder = client.prepareSearch("blog").
                setTypes("article").
                setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(boolQuery);
        //System.out.println(builder);
        SearchResponse searchResponse = builder.get();
        List> result = new ArrayList>();

        for (SearchHit hit : searchResponse.getHits()) {
            result.add(hit.getSourceAsMap());
        }
        return result;
    }

    public static String add(String title, String content, String articleClassify,
                             Date date, TransportClient client) {
        try {
            XContentBuilder xContentBuilder = XContentFactory.
                    jsonBuilder().
                    startObject().
                    field("title", title).
                    field("content", content).
                    field("articleClassify", articleClassify).
                    field("data", date).
                    endObject();
            IndexResponse result = client.prepareIndex("blog", "article").setSource(xContentBuilder).get();
            return result.getId();
        } catch (IOException e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    public static String delete(String id, TransportClient client) {
        DeleteResponse deleteResponse = client.prepareDelete("blog", "article", id).get();
        return deleteResponse.getResult().toString();
    }

    public static String update(String id, Article article, TransportClient client) {
        UpdateRequest updateRequest = new UpdateRequest("blog", "article", id);
        try {
            XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
            builder.field("title", article.getTitle());
            builder.field("content", article.getContent());
            builder.field("articleClassify", article.getArticleClassify());
            builder.field("data", article.getAddTime());
            builder.endObject();
            updateRequest.doc(builder);
            UpdateResponse result = client.update(updateRequest).get();
            return result.getResult().toString();
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }
}

说明:虽然上面很多地方写死了,但是我们的需求就是查出索引为blog,type为article下,与搜索关键字匹配的文章,与文章的标题,内容,分类进行匹配,用should,相当于mysql里的or。再次说明一点,如果你要这样子写,你必须去改es里的一个配置文件,详情看我的另外一篇文章:elasticsearch报错解决办法:NoNodeAvailableException[None of the configured nodes are available至于同步嘛,就交给logstash去做,它会每分钟去查mysql然后更新es里的内容,但是这样子坏处也很多,因为一个es部署得1.3G,一个logstash部署得770mb,两个加起来就2G多的运行内存了,所以最后,我们的博客没办法加上es,因为租借的阿里云服务器就2G运行内存.....

最后看看效果,postman查看一下logstash同步后es里的全部数据:

spirngboot集成elasticsearch_第1张图片

我们通过接口查一下关键词为”恶龙“的文章:

spirngboot集成elasticsearch_第2张图片

spirngboot集成elasticsearch_第3张图片

看到TotaltimeMillis,这是我之前在java代码里插入了一个程序执行时间的计时器,看看,我们查询到数据仅仅只需要7ms,这个速度很惊人。

不过这个代码使用了默认的分词器standard,这个分词器会把中文分成一个个单词去匹配,这样子就会出现,你要你文章存在一个与关键字里一个中文字符匹配就会算匹配成功,就是说你本来想要查有关中国人的文章,结果有的文章并没有“中国人”这个词却有“中”或者“国”再或者有"人"这个词,就会算是匹配成功,这显然不是我们想要的结果。但是在这里不做分词器的介绍,如果感兴趣的小伙伴可以去github查看一下es的中文分词插件ik。

下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases?after=v6.4.2

你可能感兴趣的:(springboot,java,elasticsearch)