美文网首页Spring之路
Spring和Elasticsearch全文搜索整合详解

Spring和Elasticsearch全文搜索整合详解

作者: 逍遥天扬 | 来源:发表于2019-07-10 11:22 被阅读3次

    Spring和Elasticsearch全文搜索整合详解

    一、概述

    ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。

    ES是ElasticSearch的缩写;

    ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是开源软件。

    一般公司都是用ELK做日志分析,社区搜索之类的,很少单独使用ElasticSearch。但是单独使用ElasticSearch也很广泛,没有ELK的时候都是这样玩的。

    比如我的社区网站(https://www.pomit.cn)就用了ElasticSearch做社区搜索,一开始做搜索的时候,曾有三种方案:

    • Mysql的全文搜索,据说很慢,而且我的mysql版本也不支持中文,还要升级。

    • 搜索引擎的支持,搜索引擎可以传入keyword、site对网站的某个网页做搜索,但是依赖于搜索引擎的收录情况。特别是百度渣渣,求它收录都难,必应还是蛮快的。但是都不够快。

    • ElasticSearch做社区搜索,需要安装ElasticSearch。用了一段时间,感觉还可以。

    首发地址:
    品茗IT-同步发布

    品茗IT 提供在线支持:

    一键快速构建Spring项目工具

    一键快速构建SpringBoot项目工具

    一键快速构建SpringCloud项目工具

    一站式Springboot项目生成

    Mysql一键生成Mybatis注解Mapper

    二、环境配置

    本文假设你已经引入Spring必备的一切了,已经是个Spring项目了,如果不会搭建,可以打开这篇文章看一看《Spring和Spring Mvc 5整合详解》

    2.1 maven依赖

    使用elasticsearch需要引入spring-data-elasticsearch,而且要保证版本和安装的elasticsearch对应。

    <?xml version="1.0"?>
    <project
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
        xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>cn.pomit</groupId>
            <artifactId>SpringWork</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <artifactId>Elasticsearch</artifactId>
        <packaging>jar</packaging>
        <name>Elasticsearch</name>
        <url>http://maven.apache.org</url>
        <properties>
            <!-- redis 版本 -->
            <elasticsearch.version>3.1.6.RELEASE</elasticsearch.version>
            
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-elasticsearch</artifactId>
                <version>${elasticsearch.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-commons</artifactId>
                <version>2.1.6.RELEASE</version>
            </dependency>
        </dependencies>
        <build>
            <finalName>Elasticsearch</finalName>
        </build>
    </project>
    
    

    父模块可以在https://www.pomit.cn/spring/SpringWork/pom.xml获取。

    2.2 Spring配置

    需要配置elasticsearchTemplate和elasticsearch:transport-client。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        
        <bean id="annotationPropertyConfigurerElasticsearch"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="order" value="1" />
            <property name="ignoreUnresolvablePlaceholders" value="true" />
            <property name="locations">
                <list>
                    <value>classpath:elasticsearch.properties</value>
                </list>
            </property>
        </bean>
       
        <elasticsearch:transport-client id="client"
            cluster-nodes="${elasticsearch.cluster-nodes}" cluster-name="${elasticsearch.cluster-name}" />
    
        <bean name="elasticsearchTemplate"
            class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
            <constructor-arg ref="client" />
        </bean>
        
         <elasticsearch:repositories base-package="cn.pomit.springwork.elasticsearch.dao" />
    </beans>
    

    elasticsearch.properties中存放elasticsearch的地址端口信息。

    elasticsearch.properties:

    elasticsearch.cluster-name=elasticsearch
    elasticsearch.cluster-nodes=127.0.0.1:9300
    
    

    三、Elasticsearch访问数据层

    我们直接使用Spring-data-elasticsearch, 一切都会变的特别简单。Spring-data-elasticsearch支持快速查询,也支持@Query之定义查询,要注意它的写法,和elasticsearch原生写法略有不同。

    QuestionElasticsearchRepository :

    package cn.pomit.springwork.elasticsearch.dao;
    
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.elasticsearch.annotations.Query;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    
    import cn.pomit.springwork.elasticsearch.domain.FQuestionElasticssearch;
    
    public interface QuestionElasticsearchRepository extends ElasticsearchRepository<FQuestionElasticssearch, Long> {
    
        Page<FQuestionElasticssearch> findByCatory(String catory, Pageable pageable);
    
        @Query("{ \"bool\":{ \"must\":[ { \"multi_match\": { \"query\": \"?0\", \"type\": \"most_fields\", \"fields\": [ \"title\", \"content\" ] } }, { \"match\": { \"catory\": \"?1\" } } ] } } ")
        Page<FQuestionElasticssearch> searchByKeyWordsAndCatory(String keyword, String catory, Pageable pageable);
    
    }
    
    
    

    这个写法和Spring-data-jpa基本上一样,应该说Spring-data系列的写法都是类同的。

    注意,FQuestionElasticssearch实体需要加上@Document注解指明Elasticssearch中的index和type。

    四、测试Elasticssearch

    我们定义一个service和web接口来做测试。

    QuestionElasticsearchService:

    package cn.pomit.springwork.elasticsearch.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    import cn.pomit.springwork.elasticsearch.dao.QuestionElasticsearchRepository;
    import cn.pomit.springwork.elasticsearch.domain.FQuestionElasticssearch;
    
    @Service
    public class QuestionElasticsearchService {
        @Autowired
        QuestionElasticsearchRepository questionElasticsearchRepository;
    
        public Page<FQuestionElasticssearch> pageByOpenAndCatory(Integer page, Integer size, String catory,
                String keyWord) {
            Pageable pageable = PageRequest.of(page, size);
            if (StringUtils.isEmpty(keyWord)) {
                return questionElasticsearchRepository.findByCatory(catory, pageable);
    
            } else {
                return questionElasticsearchRepository.searchByKeyWordsAndCatory(keyWord, catory, pageable);
    
            }
        }
    }
    
    

    ElasticsearchRest:

    package cn.pomit.springwork.elasticsearch.web;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import cn.pomit.springwork.elasticsearch.domain.FQuestionElasticssearch;
    import cn.pomit.springwork.elasticsearch.service.QuestionElasticsearchService;
    
    @RestController
    @RequestMapping("/elsearch")
    public class ElasticsearchRest {
    
        @Autowired
        QuestionElasticsearchService questionElasticsearchService;
    
        @RequestMapping(value = "/test", method = { RequestMethod.GET })
        public List<FQuestionElasticssearch> test(@RequestParam(value = "value", required = false) String value) {
            return questionElasticsearchService.pageByOpenAndCatory(0, 10, "Spring专题", value).getContent();
        }
    }
    
    
    

    五、过程中用到的实体

    FQuestionElasticssearch:

    详细完整的实体,可以访问品茗IT-博客《Spring和Elasticsearch全文搜索整合详解》进行查看

    全部代码可以在Spring组件化构建https://www.pomit.cn/java/spring/spring.html中的E组件中查看,并下载。

    快速构建项目

    Spring组件化构建

    SpringBoot组件化构建

    SpringCloud服务化构建

    喜欢这篇文章么,喜欢就加入我们一起讨论SpringBoot技术吧!


    品茗IT交流群

    相关文章

      网友评论

        本文标题:Spring和Elasticsearch全文搜索整合详解

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