美文网首页javaSpringboot整合Java 杂谈
springboot整合elasticsearch全文检索入门

springboot整合elasticsearch全文检索入门

作者: 垃圾简书_吃枣药丸 | 来源:发表于2018-10-23 21:15 被阅读308次

    只是简单的整合介绍

    # 安装

    下载elasticsearch与kibana https://www.elastic.co/start

    # 依赖

    springBootVersion = '2.0.5.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-elasticsearch'
     //请与spring-boot-starter-data-elasticsearch的jar包版本一致
    compile('org.elasticsearch.client:transport:5.6.11') 
    

    springBoot 2.0.5.RELEASE 起步依赖的elasticsearch的版本是 5.6.11


    image.png

    # 配置

    1. 可在application.yml中配置
    spring:
      data:
        # 全文检索 elasticsearch
        elasticsearch:
          cluster-name: elasticsearch #节点名称
          cluster-nodes: 127.0.0.1:9300 #节点地址
          repositories:
            enabled: true
    
    1. 也可以通过java代码进行配置
    package com.futao.springmvcdemo.foundation.configuration
    
    import org.elasticsearch.client.transport.TransportClient
    import org.elasticsearch.common.settings.Settings
    import org.elasticsearch.common.transport.InetSocketTransportAddress
    import org.elasticsearch.transport.client.PreBuiltTransportClient
    import org.springframework.context.annotation.Bean
    import org.springframework.context.annotation.Configuration
    import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories
    import java.net.InetAddress
    
    /**
     * @author futao
     * Created on 2018/10/22.
     * ElasticSearch全文检索配置类
     * 可替代配置文件中的配置
     */
    @Configuration
    @EnableElasticsearchRepositories(basePackages = ["com.futao.springmvcdemo.dao"])
    open class ElasticSearchConfiguration {
    
        @Bean
        open fun client(): TransportClient {
            val node = InetSocketTransportAddress(
                    InetAddress.getByName("127.0.0.1"), 9300)
            val settings = Settings.builder()
                    .put("cluster.name", "springboot-elasticsearch")    //集群名称可以在\elasticsearch\config\elasticsearch.yml中配置
                    .build()
            return PreBuiltTransportClient(settings).addTransportAddress(node)
        }
    }
    

    # 名词解释

    elasticsearch中的名词与mysql中的名字对比


    image.png

    # 使用

    个人理解:相当于mysql的建表,程序跑起来之后会建立相应的index与type,后续程序中就可以使用该类型的index与type进行crud

    package com.futao.springmvcdemo.model.entity;
    
    import org.springframework.data.elasticsearch.annotations.Document;
    
    /**
     * @author futao
     * Created on 2018/10/20.
     * 文章
     * indexName=database
     * type=table
     * row=document
     * colnum=field
     */
    @Document(indexName = "futao", type = "article")
    public class Article extends BaseEntity {
        /**
         * 标题
         */
        private String title;
        /**
         * 简介
         */
        private String description;
        /**
         * 内容
         */
        private String content;
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    }
    

    # 插入数据

    • Dao层
    package com.futao.springmvcdemo.dao.impl
    
    import com.futao.springmvcdemo.model.entity.Article
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository
    
    /**
     * @author futao
     * Created on 2018/10/22.
     */
    interface ArticleSearchDao : ElasticsearchRepository<Article, String> {
    }
    
    • Service层
    package com.futao.springmvcdemo.service.impl
    
    import com.alibaba.fastjson.JSONObject
    import com.futao.springmvcdemo.dao.ArticleDao
    import com.futao.springmvcdemo.dao.impl.ArticleSearchDao
    import com.futao.springmvcdemo.foundation.LogicException
    import com.futao.springmvcdemo.model.entity.Article
    import com.futao.springmvcdemo.model.entity.constvar.ErrorMessage
    import com.futao.springmvcdemo.service.ArticleService
    import com.futao.springmvcdemo.utils.currentTimeStamp
    import com.futao.springmvcdemo.utils.getFieldName
    import com.futao.springmvcdemo.utils.uuid
    import org.elasticsearch.client.Client
    import org.elasticsearch.index.query.QueryBuilders
    import org.springframework.data.redis.core.RedisTemplate
    import org.springframework.stereotype.Service
    import javax.annotation.Resource
    
    /**
     * @author futao
     * Created on 2018/10/20.
     */
    @Service
    open class ArticleServiceImpl : ArticleService {
        @Resource
        private lateinit var elasticsearch: ArticleSearchDao
    
        @Resource
        private lateinit var client: Client
    
        override fun list(): List<Article> {
            val list = articleDao.list()
            elasticsearch.saveAll(list)
            return list
        }
     /**
         * 全文检索
         */
        override fun search(key: String): ArrayList<Article> {
            val hits = client.prepareSearch("futao")
                    .setTypes("article")
                    .setQuery(
                            QueryBuilders
                                    .boolQuery()
                                    .should(QueryBuilders.matchQuery(Article::getContent.getFieldName(), key))
                                    .should(QueryBuilders.matchQuery(Article::getTitle.getFieldName(), key))
                                    .should(QueryBuilders.matchQuery(Article::getDescription.getFieldName(), key))
    
                    )
                    .execute()
                    .actionGet()
                    .hits
            val list: ArrayList<Article> = arrayListOf()
            hits.forEach { it -> list.add(JSONObject.parseObject(it.sourceAsString, Article::class.java)) }
            return list
        }
    }
    
    • controller层
    package com.futao.springmvcdemo.controller.business;
    
    import com.futao.springmvcdemo.model.entity.Article;
    import com.futao.springmvcdemo.model.entity.SingleValueResult;
    import com.futao.springmvcdemo.service.ArticleService;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    /**
     * @author futao
     * Created on 2018/10/20.
     */
    @RestController
    @RequestMapping(path = "article", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public class ArticleController {
        @Resource
        private ArticleService articleService;
    
        /**
         * 新增文章
         *
         * @param title
         * @param desc
         * @param content
         * @return
         */
        @PostMapping(path = "add")
        public SingleValueResult add(
                @RequestParam("title") String title,
                @RequestParam("desc") String desc,
                @RequestParam("content") String content
        ) {
            articleService.add(title, desc, content);
            return new SingleValueResult("success");
        }
    
        /**
         * 文章列表
         *
         * @return
         */
        @GetMapping("list")
        public List<Article> list() {
            return articleService.list();
        }
    
        /**
         * 全文检索
         *
         * @param key
         * @return
         */
        @GetMapping("search")
        public List<Article> search(@RequestParam("key") String key) {
            return articleService.search(key);
        }
    }
    
    • 在启动项目之前如果程序有抛出java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]异常,则需要在启动类中添加:
    package com.futao.springmvcdemo;
    
    import com.alibaba.fastjson.parser.ParserConfig;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
    
    /**
     * @author futao
     * ServletComponentScan 开启servlet和filter
     */
    @SpringBootApplication
    @ServletComponentScan
    @MapperScan("com.futao.springmvcdemo.dao")
    @EnableCaching
    //@EnableAspectJAutoProxy
    @EnableElasticsearchRepositories(basePackages = "com.futao.springmvcdemo")
    public class SpringmvcdemoApplication {
        public static void main(String[] args) {
            /**
             * 添加elasticsearch之后发生异常的解决方案
             * Springboot整合Elasticsearch 在项目启动前设置一下的属性,防止报错
             * 解决netty冲突后初始化client时会抛出异常
             * java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]
             */
            System.setProperty("es.set.netty.runtime.available.processors", "false");
    
            SpringApplication.run(SpringmvcdemoApplication.class, args);
            /**
             * redis反序列化
             * 开启fastjson反序列化的autoType
             */
            ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        }
    }
    

    # 测试

    • 启动项目,可以在health中查看到相关的健康状况


      elasticsearch健康状况
    • list接口请求(把数据放入elasticsearch中)


      将数据放入elasticsearch中
    • 现在可以在kibana中查看到上面存入的数据


      kibana
    • 也可以进行简单的搜索测试


      test
    • 调用search接口测试


      search

    elasticsearch数据的存放位置(删除该文件夹下的数据即删除了所有的索引)


    data存放地址

    多的不说了,跟之前项目中用过的Hibernate Search很像,不过elasticsearch也是在架构层面实现的全文索引,elasticsearch可以部署在其他服务器上,减轻主服务器的压力,并通过http restful api的形式与主程序进行协调工作。elasticsearch一般通过集群方式进行部署,横向扩展非常简单,甚至只需要改几行配置就行。

    相关文章

      网友评论

        本文标题:springboot整合elasticsearch全文检索入门

        本文链接:https://www.haomeiwen.com/subject/zixzzftx.html