Spring Boot接入Elasticsearch

Spring boot 接入ES

最终效果:

最终效果
效果丑,也就那么意思一下;因为sping boot已经集成了es,所以接入es只需要很简单的配置一下就好了。当然事先得下载好es,我用的是windows 6.5.3版本,没有遇到什么版本冲突问题,至于安装es和建立spring boot项目我就不细说了。

代码:

pom.xml


        
            org.springframework.boot
            spring-boot-starter-data-elasticsearch
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.2
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            mysql
            mysql-connector-java
            runtime
        

        
        
            com.alibaba
            fastjson
            1.2.54
        

        
            org.springframework.boot
            spring-boot-devtools
            true
            true
        


    

引入需要的jar包就好

application.yml

spring:
  datasource:
    hikari:
      jdbc-url: jdbc:mysql://url:port/database
      username: username
      password: password
      driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://url:port/database
    username: username
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  thymeleaf:
    cache: false
    prefix: classpath:templates/
    suffix: .html
    mode: HTML
    encoding: UTF-8
  data:
    elasticsearch:
      cluster-name: es-test
      cluster-nodes: localhost:9300
      repositories:
        enabled: true
  main:
    allow-bean-definition-overriding: true
server:
  port: 80
mybatis:
  type-aliases-package: com.xxx.xxx.xxx

cluster-name就是自己设置的es集群名称,可以在es安装目录下面的config/elasticsearch.yml配置

实体类

package com.xxx.xxx.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.util.Date;

@Document(indexName = "test", type = "company")
public class Company {
    @Id
    private String id;

    @Field(analyzer = "ik",searchAnalyzer = "ik",store = true,type = FieldType.Text)
    private String cname;

    private String ename;

    private String iname;

    private String scode;

    private String amt;

    private String person;

    @Field
    private Date btime;

    @Field
    private Date sbtime;

    @Field
    private Date ptime;

    private String address;

    private String tel;

    private String fax;

    private String web;

    private String email;

    private String sec;

    @Field(analyzer = "ik",searchAnalyzer = "ik",store = true,type = FieldType.Text)
    private String industry;

    private String business;

    private String recommend;

    private String over;

    private Date ctime;

    @Field(analyzer = "ik",searchAnalyzer = "ik",store = true,type = FieldType.Text)
    private String industry2;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id == null ? null : id.trim();
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname == null ? null : cname.trim();
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename == null ? null : ename.trim();
    }

    public String getIname() {
        return iname;
    }

    public void setIname(String iname) {
        this.iname = iname == null ? null : iname.trim();
    }

    public String getScode() {
        return scode;
    }

    public void setScode(String scode) {
        this.scode = scode == null ? null : scode.trim();
    }

    public String getAmt() {
        return amt;
    }

    public void setAmt(String amt) {
        this.amt = amt == null ? null : amt.trim();
    }

    public String getPerson() {
        return person;
    }

    public void setPerson(String person) {
        this.person = person == null ? null : person.trim();
    }

    public Date getBtime() {
        return btime;
    }

    public void setBtime(Date btime) {
        this.btime = btime;
    }

    public Date getSbtime() {
        return sbtime;
    }

    public void setSbtime(Date sbtime) {
        this.sbtime = sbtime;
    }

    public Date getPtime() {
        return ptime;
    }

    public void setPtime(Date ptime) {
        this.ptime = ptime;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address == null ? null : address.trim();
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel == null ? null : tel.trim();
    }

    public String getFax() {
        return fax;
    }

    public void setFax(String fax) {
        this.fax = fax == null ? null : fax.trim();
    }

    public String getWeb() {
        return web;
    }

    public void setWeb(String web) {
        this.web = web == null ? null : web.trim();
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email == null ? null : email.trim();
    }

    public String getSec() {
        return sec;
    }

    public void setSec(String sec) {
        this.sec = sec == null ? null : sec.trim();
    }

    public String getIndustry() {
        return industry;
    }

    public void setIndustry(String industry) {
        this.industry = industry == null ? null : industry.trim();
    }

    public String getBusiness() {
        return business;
    }

    public void setBusiness(String business) {
        this.business = business == null ? null : business.trim();
    }

    public String getRecommend() {
        return recommend;
    }

    public void setRecommend(String recommend) {
        this.recommend = recommend == null ? null : recommend.trim();
    }

    public String getOver() {
        return over;
    }

    public void setOver(String over) {
        this.over = over == null ? null : over.trim();
    }

    public Date getCtime() {
        return ctime;
    }

    public void setCtime(Date ctime) {
        this.ctime = ctime;
    }

    public String getIndustry2() {
        return industry2;
    }

    public void setIndustry2(String industry2) {
        this.industry2 = industry2 == null ? null : industry2.trim();
    }
}

@Id注解就是插入到es中当id的字段,@Field表明你想要查询的字段,中文字段用到ik分词器,如果不想被解析可以设置type=FieldType.Keyword。我的数据是同事从网上扒下来的,所以字段看上去有点奇怪,另外这实体类是用mybatis generator逆向生成的。

Repository接口

package com.xxx.xxx.mapper;

import com.jyw.es.model.Company;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * @author jiangyw
 * @date 2019/1/22 10:17
 */
public interface ICompanyRepository extends ElasticsearchRepository {

}

这就是crud操作的接口,可以自定义一些方法,类似于mybatis的mapper接口

Controller

package com.xxx.xxx.controller;

import com.alibaba.fastjson.JSONObject;
import com.jyw.es.model.Company;
import com.jyw.es.service.ICompany;
import com.jyw.es.mapper.ICompanyRepository;
import org.apache.lucene.document.Field;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
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.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author jiangyw
 * @date 2019/1/18 20:02
 */
@RestController
@RequestMapping("company")
public class CompanyController {
    @Resource
    private ICompany companyService;
    @Resource
    private ICompanyRepository companyRepository;
    @Resource
    private ElasticsearchTemplate elasticsearchTemplate;

    @GetMapping("all")
    public String all() {
        List list = companyService.listAll();
        return JSONObject.toJSONString(list);
    }

    /**
     * 把数据库里的数据导入es中
     */
    @GetMapping("save")
    public String save() {
        List list = companyService.listAll();
        Iterable companies = companyRepository.saveAll(list);
        return JSONObject.toJSONString(companies);
    }


    /**
     * 搜索
     *
     * @param keyword keyword
     */
    @PostMapping("search")
    public String search(@RequestParam("keyword") String keyword) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.should(QueryBuilders.matchQuery("cname", keyword));
        queryBuilder.should(QueryBuilders.matchQuery("industry", keyword));
        queryBuilder.should(QueryBuilders.matchQuery("industry2", keyword));
        Pageable pageable = PageRequest.of(0, 10);
        Iterable companies = companyRepository.search(queryBuilder, pageable);
        return JSONObject.toJSONString(companies);
    }

    /**
     * 搜索(高亮)
     *
     * @param keyword keyword
     */
    @PostMapping("hsearch")
    public String hSearch(@RequestParam("keyword") String keyword) {
        Pageable pageable = PageRequest.of(0, 10);

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.should(QueryBuilders.matchQuery("cname", keyword));
        queryBuilder.should(QueryBuilders.matchQuery("industry", keyword));
        queryBuilder.should(QueryBuilders.matchQuery("industry2", keyword));

        String preTag = "";
        String postTag = "";

        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withHighlightFields(new HighlightBuilder.Field("cname").preTags(preTag).postTags(postTag),
                        new HighlightBuilder.Field("industry").preTags(preTag).postTags(postTag),
                        new HighlightBuilder.Field("industry2").preTags(preTag).postTags(postTag)
                )
                .withPageable(pageable)
                .build();

        AggregatedPage companies = elasticsearchTemplate.queryForPage(searchQuery, Company.class, new SearchResultMapper() {
            @Override
            public  AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) {
                List list = new ArrayList<>();
                for (SearchHit hit : response.getHits()) {
                    Company company = new Company();
                    HighlightField cname = hit.getHighlightFields().get("cname");
                    if (cname != null) {
                        company.setCname(cname.getFragments()[0].string());
                    }else {
                        company.setCname(hit.getSourceAsMap().get("cname").toString());
                    }

                    HighlightField industry = hit.getHighlightFields().get("industry");
                    if (industry != null) {
                        company.setIndustry(industry.getFragments()[0].toString());
                    }else {
                        company.setCname(hit.getSourceAsMap().get("industry").toString());
                    }
                    HighlightField industry2 = hit.getHighlightFields().get("industry2");
                    if (industry2 != null) {
                        company.setIndustry2(industry2.getFragments()[0].toString());
                    }else {
                        company.setCname(hit.getSourceAsMap().get("industry2").toString());
                    }
                    list.add(company);
                }
                return new AggregatedPageImpl<>((List) list);
            }
        });

        return JSONObject.toJSONString(companies);
    }
}

就这几个简单的接口……先调用一下save接口,把MySQL数据中的数据存入es,可以用kibana查看数据:
kibana查看数据
可以看到数据已经成功导入了

前端代码




    
    Title

    
    

    
    

    

这里我并没有用到Thymeleaf模板,就是普通的前端html;所以服务端要设置一下,允许跨域请求。

package com.xxx.xxx.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * 允许跨域
 *
 * @author jiangyw
 * @date 2019/1/22 15:25
 */
@Configuration
public class MyConfig {


    @Bean
    public CorsFilter config() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");

        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }
}

搜索结果数据

{
    "content": [
        {
            "cname": "无锡精密股份有限公司",
            "industry": "普制造行业",
            "industry2": "普制造行业"
        },
        {
            "cname": "上海首达包装材料股份有限公司",
            "industry": "行业",
            "industry2": "行业"
        },
        {
            "cname": "上海恒浥智能科技股份有限公司",
            "industry": "其他",
            "industry2": "其他业"
        },
        {
            "cname": "上海狮虎能源科技股份有限公司",
            "industry": "普制造业",
            "industry2": "普制造业"
        },
        {
            "cname": "上海大椿建筑股份有限公司",
            "industry": "其他专用(行业代码 260207)",
            "industry2": "其他专用"
        },
        {
            "cname": "上海隆友精密刀具股份有限公司",
            "industry": "制造",
            "industry2": "制造业"
        },
        {
            "cname": "上海申雁制冷设备股份有限公司",
            "industry": "设备",
            "industry2": "设备业"
        },
        {
            "cname": "积康螺杆制造(上海)股份有限公司",
            "industry": "基础件",
            "industry2": "基础件"
        },
        {
            "cname": "上海明索重型股份有限公司",
            "industry": "床工具行业",
            "industry2": "床工具行业"
        },
        {
            "cname": "上海裕强户外用品股份有限公司",
            "industry": "制造行业",
            "industry2": "制造行业"
        }
    ],
    "empty": false,
    "facets": [
        
    ],
    "first": true,
    "last": true,
    "maxScore": 0.0,
    "number": 0,
    "numberOfElements": 10,
    "pageable": "INSTANCE",
    "size": 0,
    "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
    },
    "totalElements": 10,
    "totalPages": 1
}

可以看到通过高亮搜索得到的结果中,关键词已经被套上接口中设定好的标签

项目结构

项目结构

总结

就是在项目中把MySQL中的数据导入es,然后通过es分词、高亮搜索;由于spring boot已经集成好了,所以并不需要我们做多少事情……

你可能感兴趣的:(Elasticsearch)