使用springboot整合elasticsearch+Vue实现数据查询

使用elasticsearch做数据服务查询:

实现springboot整合elasticsearchhe和vue做数据查询
注意:在进行此开发的时候一定要保证elasticsearch的版本与springboot的版本对应,否则可能会无法连接,这里用的elasticsearch和springboot的版本分别是5.6.16和2.2.1
elasticsearch仅支持1.8及1.8以上的jdk版本

开发工具

  • 后台开发:Idea;
  • 后台测试:Postman;
  • 前端开发:VScode;

elasticsearch服务搭建(Windows环境):

1、下载安装elasticsearch:官网地址

2、运行elasticsearch:

下载完解压即可:直接双击/bin/ElasticSearch.bat
使用springboot整合elasticsearch+Vue实现数据查询_第1张图片
一般来说,出现start即为启动成功。

3、浏览器输入:http://127.0.0.1:9200 查看效果:

使用springboot整合elasticsearch+Vue实现数据查询_第2张图片

4、安装node.js。

5、安装grunt-cli:

安装node.js的目录下,输入栏中输入cmd即可进入cmd命令操作符界面;
输入 npm install -g grunt-cli;
输入 grunt -version查看版本;
如果此时报错“grunt不是内部或外部命令,也不是可运行的程序 或批处理文件”,

解决方案:

①进入C:\Users\Administrator\AppData\Roaming\npm,将此路径添加到环境变量PATH中。然后重新打开输入,依旧报错请执行第②步

②进入nodejs安装目录,将如下文件复制到C:\Users\Administrator\AppData\Roaming\npm;然后进入nodejs的node_global目录,将grunt-cli和npm文件夹整体复制到C:\Program Files\nodejs\node_global\node_modules中。

6、安装elasticsearch-head:

安装:https://blog.csdn.net/mjlfto/article/details/79772848

另外一种方法,可通过谷歌的网上应用店进行下载安装elasticsearch-head到扩展程序即可(问题请自行解决)。

7、查看:

浏览器中输入:http://localhost:9100 查看,谷歌浏览器安装直接双击该扩展程序即可。
在这里插入图片描述

8、下载logstash:

网址https://www.elastic.co/cn/downloads/logstash;
解压,进入解压目录的lib\jars文件夹,放入数据库连接jar包,进入解压目录下bin文件夹下,创建jdbc.sql,logstash.conf文件。
注意:解压目录不能出现中文。
jdbc.sql 文件放入自己所需的查询SQL语句。
logstash.conf文件输入以下内容:

input {
    stdin {
    
    }
    jdbc {
       # mysql 数据库链接
      jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/vue?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC"
      # 用户名和密码
      jdbc_user => "root"
      jdbc_password => "root"
      # 驱动 修改为mysql连接包位置
      jdbc_driver_library => "D:\DevelopSoftware\logstash-7.4.2\logstash-7.4.2\logstash-core\lib\jars\mysql-connector-java-5.1.37-bin.jar"
      # 驱动类名
      jdbc_driver_class => "com.mysql.jdbc.Driver"
      jdbc_paging_enabled => "true"
      jdbc_page_size => "50000"
#你的SQL的位置,当然,你的SQL也可以直接写在这里。
      #statement => select * from aaa
      # 执行的sql 文件路径+名称 
      statement_filepath => "jdbc.sql"
      # 设置监听间隔  各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
      schedule => "* * * * *"
    }
}
output {
    elasticsearch {
        # ES的IP地址及端口
        hosts => ["localhost:9200"]
        # 索引名称 可自定义
        index => "test02"
        # 需要关联的数据库中有有一个id字段,对应类型中的id
        document_id => "%{cid}"
        document_type => "test02"
    }
    stdout {
        # JSON格式输出
        codec => json_lines
    }
}

在解压的目录的bin目录下运行cmd输入 logstash -f logstash.conf。
注意:此工具不能停止运行,一旦停止运行,则无法实时同步数据库的数据!

9、elasticsearch-head连接elasticsearch服务端口进行数据查询:

使用springboot整合elasticsearch+Vue实现数据查询_第3张图片
使用springboot整合elasticsearch+Vue实现数据查询_第4张图片
elasticsearch服务器搭建完成。

后台开发:

如何搭建springboot项目请参考此博文,这里不再详细叙述:https://blog.csdn.net/weixin_43303530/article/details/103059004

以下是该项目的依赖及配置:


            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-data-elasticsearch
        
        
            org.apache.commons
            commons-lang3
        
        
            mysql
            mysql-connector-java
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
server:
  port: 8888
spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 127.0.0.1:9300
    #\u4E0B\u9762\u4E00\u9879\u7684\u914D\u7F6E\u7528\u4E8E\u8FD4\u56DE\u4FE1\u606F\u65F6
  jackson:
    default-property-inclusion: non_null
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/vue?useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    jpa:
      hibernate:
        ddl-auto: update  # \u7B2C\u4E00\u6B21\u5EFA\u8868create  \u540E\u9762\u7528update\uFF0C\u8981\u4E0D\u7136\u6BCF\u6B21\u91CD\u542F\u90FD\u4F1A\u65B0\u5EFA\u8868
      show-sql: true

编写实体类:

package com.elasticsearch.pojo;

import lombok.Data;
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;


@Data
@Document(indexName = "test02", type = "test02", shards = 1, replicas = 0)
public class Goods {

    @Id
    private Long cid;
//    @Field(type = FieldType.Keyword, analyzer = "ik_max_word")
//    private String all; // 所有需要被搜索的信息,包含标题,分类,甚至品牌, analyzer = "ik_max_word"
    @Field(type = FieldType.Auto, index = true)
    private String name;
    private String isParent;
    private String parentId;
    private Long level;
    private String pathid;
}

@Document的作用
分页控制:

package com.elasticsearch.pojo;

public class SearchRequest {
    private String key;// 搜索条件

    private Integer page;// 当前页

    private static final Integer DEFAULT_SIZE = 10;// 每页大小,不从页面接收,而是固定大小
    private static final Integer DEFAULT_PAGE = 1;// 默认页

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public Integer getPage() {
        if(page == null){
            return DEFAULT_PAGE;
        }
        // 获取页码时做一些校验,不能小于1
        return Math.max(DEFAULT_PAGE, page);
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getSize() {
        return DEFAULT_SIZE;
    }
}

数据库对应实体:

package com.elasticsearch.pojo;

import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import javax.persistence.*;
import java.io.Serializable;

@Data
@Entity(name="wp_ex_source_goods_tb_cat_copy")
public class XcGoods implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cid")
    private Long cid;
    @Column(name = "name")
    private String name;
    @Column(name = "is_parent")
    private String isParent;
    @Column(name = "parent_id")
    private String parentId;
    @Column(name = "level")
    private Long level;
    @Column(name = "pathid")
    private String pathid;
    @Column(name = "path")
    private String path;
}

dao编写:

package com.elasticsearch.repository;

import com.elasticsearch.pojo.XcGoods;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface XcGoodsRepository extends JpaRepository, JpaSpecificationExecutor {

}

service编写:

可省略service接口,且结构较为简单,这里不再贴出service的接口代码。

package com.elasticsearch.service.impl;

import com.elasticsearch.pojo.Goods;
import com.elasticsearch.pojo.SearchRequest;
import com.elasticsearch.pojo.SearchResult;
import com.elasticsearch.pojo.XcGoods;
import com.elasticsearch.repository.GoodsRepository;
import com.elasticsearch.service.SearchService;
import com.elasticsearch.utils.PageResult;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SearchServiceImpl implements SearchService {


    @Autowired
    private GoodsRepository goodsRepository;

    @Autowired
    private ElasticsearchTemplate template;

    @Override
    public Goods buildGoods(XcGoods xcgoods) {
        //搜索字段
//        String all =  xcgoods.getName();

        //构建goods对象
        Goods goods = new Goods();
        goods.setCid(xcgoods.getCid());
        goods.setName(xcgoods.getName());
        goods.setIsParent(xcgoods.getIsParent());
        goods.setParentId(xcgoods.getParentId());
        goods.setPathid(xcgoods.getPathid());
        goods.setLevel(xcgoods.getLevel());
        // 搜索字段,包含标题,分类,品牌,规格,等等
//        goods.setAll(all);

        return goods;
    }


    @Override
    public PageResult search(SearchRequest request) {
        int page = request.getPage() - 1;
        int size = request.getSize();
        //创建查询构建器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        //结果过滤
        queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{"cid", "name"}, null));

        //分页
        queryBuilder.withPageable(PageRequest.of(page, size));
        //过滤
        queryBuilder.withQuery(QueryBuilders.matchQuery("name", request.getKey()));

        //查询
        //Page result = goodsRepository.search(queryBuilder.build());
        AggregatedPage result = template.queryForPage(queryBuilder.build(), Goods.class);

        //解析结果
        //分页结果解析
        long total = result.getTotalElements();
        Integer totalPages1 = result.getTotalPages();    //失效
        Long totalPages = total % size == 0 ? total / size : total / size + 1;
        List goodsList = result.getContent();

        //解析聚合结果

        return new SearchResult(total, totalPages, goodsList);
    }
}

controller层编写:

package com.elasticsearch.web;

import com.elasticsearch.pojo.Goods;
import com.elasticsearch.pojo.SearchRequest;
import com.elasticsearch.service.SearchService;
import com.elasticsearch.utils.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class SearchController {
    @Autowired
    private SearchService searchService;

    /**
     * 搜索功能
     * @param request
     * @return
     */
    @GetMapping("search")
    public ResponseEntity> search(SearchRequest request) {
        return ResponseEntity.ok(searchService.search(request));
    }
}

工具类:

package com.elasticsearch.utils;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult {
    private Long total;// 总条数
    private Long totalPage;// 总页数
    private List items;// 当前页数据

    public PageResult(Long total, List items) {
        this.total = total;
        this.items = items;
    }
}

跨域问题:

在config包下创建该配置文件,文件名可自行更改:

package com.elasticsearch.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;

@Configuration
public class CorsConfig {
    // 初始化 CorsConfiguration 对象并设置允许的域名、请求头部信息和请求方式
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 允许任何域名使用
        corsConfiguration.addAllowedHeader("*"); // 2 允许任何头
        corsConfiguration.addAllowedMethod("*"); // 3 允许任何方法(post、get 等)
        return corsConfiguration;
    }
    /**
     * 创建 CorsFilter 对象
     * @return CorsFilter
     */
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new
                UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); //拦截所有请求
        return new CorsFilter(source);
    }
}

项目结构:
使用springboot整合elasticsearch+Vue实现数据查询_第5张图片

测试:

使用Postman进行测试

Postman下载使用
使用springboot整合elasticsearch+Vue实现数据查询_第6张图片

前台开发:

在进行前台开发前,一定要确认已安装了node.js和Vue-cli
webpack+vue2.0+nodeJs搭建环境

现在,我们进入前台页面的开发,这里我使用的前台开发软件为VScode,使用的前端框架为Vue

1、搭建Vue-cli脚手架并创建一个基于 webpack 模板的新项目:

项目创建:打开终端(快捷键 Ctrl+~),输入命令行
vue init webpack projectName,projectName 为你的项目名称

2、启动项目确保项目初始化没有问题

3、安装axios 插件和安装 Element 插件 :

安装axios:npm install --save axios vue-axios

4、前端页面编写:




尚未解决:该页面中使用的p标签报错,但不影响运行
使用springboot整合elasticsearch+Vue实现数据查询_第7张图片
运行页面:
使用springboot整合elasticsearch+Vue实现数据查询_第8张图片
使用springboot整合elasticsearch+Vue实现数据查询_第9张图片

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