实现springboot整合elasticsearchhe和vue做数据查询
注意:在进行此开发的时候一定要保证elasticsearch的版本与springboot的版本对应,否则可能会无法连接,这里用的elasticsearch和springboot的版本分别是5.6.16和2.2.1
elasticsearch仅支持1.8及1.8以上的jdk版本
下载完解压即可:直接双击/bin/ElasticSearch.bat
一般来说,出现start即为启动成功。
安装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中。
安装:https://blog.csdn.net/mjlfto/article/details/79772848
另外一种方法,可通过谷歌的网上应用店进行下载安装elasticsearch-head到扩展程序即可(问题请自行解决)。
浏览器中输入:http://localhost:9100 查看,谷歌浏览器安装直接双击该扩展程序即可。
网址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。
注意:此工具不能停止运行,一旦停止运行,则无法实时同步数据库的数据!
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;
}
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的接口代码。
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);
}
}
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);
}
}
使用Postman进行测试
在进行前台开发前,一定要确认已安装了node.js和Vue-cli
webpack+vue2.0+nodeJs搭建环境
现在,我们进入前台页面的开发,这里我使用的前台开发软件为VScode,使用的前端框架为Vue
项目创建:打开终端(快捷键 Ctrl+~),输入命令行
vue init webpack projectName,projectName 为你的项目名称
安装axios:npm install --save axios vue-axios