springBoot+Window下的Elasticsearch实现查询
Posted autonomy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springBoot+Window下的Elasticsearch实现查询相关的知识,希望对你有一定的参考价值。
1.准备好Elasticsearch环境,这里使用的是window版本。
1.从官网下载安装包:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-5-6-16
2.分词器 elasticsearch-analysis-ik:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v5.6.16
3.head插件 地址:https://github.com/mobz/elasticsearch-head
其他环境:node.js环境(可视化运行界面运行需要),jdk8
4. 将下载好的安装包解压,进入bin目录运行elasticsearch.bat即可。(需要jdk8的环境)
成功启动后访问:http://localhost:9200/,返回信息:
5. 可以通过head插件查看可视化页面。
6. 将head解压到(建议解压到Elasticsearch的统计目录,好找),进入到elasticsearch-head-master即可(需要node.js环境)。
7.在此页面数据 grunt server,即可运行。如果提示无法启动。运行命令:npm install -g grunt-cli。
8.使用可是化界面连接 Elasticsearch 时 需要在Elasticsearch 的配置文件下配置跨域。配置文件位置:elasticsearch-5.6.16configelasticsearch.yml。
配置内容: http.cors.enabled: true
http.cors.allow-origin: "*"
注意:“:” 号后需要加空格
9.访问 http://localhost:9100/.
10,现在的 Elasticsearch 就是一个服务器,并且已有了视化界面,我们可以在可视化界面对他进行操作,但在elasticsearch-head-master上操作它时太过于麻烦。
这里选择postman对他进行操作。在操作之前,先看一下数据库(使用mysql)和索引库之间的关系。深入了解概念可参考:
https://blog.csdn.net/achang07/article/details/79713245
对应关系:
11. 首先创建一个索引库,然后在创建一个mapping,或者在创建索引库的同时创建mapping。
11.1创建索引库
11.2 创建映射
查看以下效果
11.3创建索引的同时创建映射
12. 对于elasticsearch的概念暂结束。接下来看后端代码。创建springBoot项目。引入以下依赖。数据库文件
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.57</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
13. application.yml配置
server: port: 8888 spring: data: elasticsearch: cluster-nodes: 127.0.0.1:9300 #在这配置数库连接是因为,我会从数据库读取数据到索引库中。 #如果有其他方式读取数据,一下配配置可以不用写 datasource: url: jdbc:mysql://127.0.0.1:3306/jpa username: root password: sasa driver-class-name: com.mysql.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true
14.在后端使用创建索引库,首先创建相对应过的实体类。
package com.los.es.pojo; import lombok.Data; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; /** * 用于创建索引库,ES */ @Data //indexName 索引库名称,类型名字:goods @Document(indexName = "tb",type = "goods") public class Rgoods { @Id private int cid; @Field(type = FieldType.Keyword,index = true,analyzer = "ik_max_word") private String name; //其他文档数据默认 private int isParent; private int parentId; private int level; private String pathId; private String path; }
14.创建索引库并存储数据
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.los.es.EsApplication; import com.los.es.config.ResponseResult; import com.los.es.pojo.Rgoods; import com.los.es.repository.GoodsRepository; import com.los.es.repository.RgoodsRepository; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; 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.NativeSearchQueryBuilder; import java.util.List; @SpringBootTest(classes = EsApplication.class) public class Init { //在导入spring-boot-starter-data-elasticsearch启动器时 // springboot已经默认配置了这个类 @Autowired private ElasticsearchTemplate template; //用于调用elasticsearch索引库的接口,如新增,查询,相关代码在后面会贴出来 @Autowired private GoodsRepository goodsRepository; //用于操作数据库的接口,相关代码在后面会贴出来 @Autowired private RgoodsRepository rgoodsRepository; //创建索引库 @Test public void createIndex(){ template.createIndex(Rgoods.class); } //向索引库中填充数据 @Test public void fullData(){ //使用了Ali的fastJson,将两个类名不一样,但其中的字段名和类型一样的类相互直接赋值 //因为我需要从数据库将数据读出来,需要建一个实体类对应数据库 rgoodsRepository.saveAll(JSONObject.parseArray (JSON.toJSONString(goodsRepository.findAll()),Rgoods.class)); }
15.项目结构,该案例使用jpa操作数据库。
16,Goods实体类
package com.los.es.pojo; import javax.persistence.*; @Entity @Table(name = "wp_ex_source_goods_tb_cat_copy") public class Goods { @Id @Column(name = "cid",insertable = false,updatable = false) @GeneratedValue(strategy = GenerationType.IDENTITY) private int cid; @Column(name = "name") private String name; @Column(name = "is_parent") private int isParent; @Column(name = "parent_id") private int parentId; @Column(name = "level") private int level; @Column(name = "pathid") private String pathId; @Column(name = "path") private String path; public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getIsParent() { return isParent; } public void setIsParent(int isParent) { this.isParent = isParent; } public int getParentId() { return parentId; } public void setParentId(int parentId) { this.parentId = parentId; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public String getPathId() { return pathId; } public void setPathId(String pathId) { this.pathId = pathId; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } }
17.Rgoods
package com.los.es.pojo; import lombok.Data; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; /** * 用于创建索引库,ES */ @Data //indexName 索引库名称,类型名字:goods @Document(indexName = "tb",type = "goods") public class Rgoods { @Id private int cid; @Field(type = FieldType.Keyword,index = true,analyzer = "ik_max_word") private String name; //其他文档数据默认 private int isParent; private int parentId; private int level; private String pathId; private String path; }
18
.
19.
20.CorsConfig 配置类
package com.los.es.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); } }
21. RequestResult
package com.los.es.config; public class RequestResult { //查询条件 private String searchKey; //当前页 private Integer page; //当前页显示条数 private Integer size; private static final Integer DEFAULT_SIZE = 20;// 每页大小,不从页面接收,而是固定大小 private static final Integer DEFAULT_PAGE = 1;// 默认页 public String getSearchKey() { return searchKey; } public void setSearchKey(String searchKey) { this.searchKey = searchKey; } 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() { if(size == null){ return DEFAULT_SIZE; } return size; } public void setSize(Integer size) { this.size = size; } }
22. ResponseResult
package com.los.es.config; import com.los.es.pojo.Rgoods; import java.util.List; /** * 返回结果 */ public class ResponseResult { private int currentPage; private int pageSize; private int total; private List<Rgoods> rgoods; public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public List<Rgoods> getRgoods() { return rgoods; } public void setRgoods(List<Rgoods> rgoods) { this.rgoods = rgoods; } /** * */ }
23. GoodsService 服务层
package com.los.es.service; import com.los.es.config.RequestResult; import com.los.es.config.ResponseResult; import com.los.es.pojo.Rgoods; import com.los.es.repository.RgoodsRepository; import org.elasticsearch.index.query.QueryBuilders; 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.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; @Service @Transactional public class GoodsService { @Autowired private RgoodsRepository rgoodsRepository; @Autowired private ElasticsearchTemplate template; public ResponseResult findByKey(RequestResult request){ int page = request.getPage() - 1; int size = request.getSize(); ResponseResult rs = new ResponseResult(); //自定义查询方法 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); //分页 queryBuilder.withPageable(PageRequest.of(page, size)); //过滤 if(!StringUtils.isEmpty(request.getSearchKey())){//条件为空时 queryBuilder.withQuery(QueryBuilders.matchQuery("name", request.getSearchKey())); } //查询 AggregatedPage<Rgoods> rgoods = template.queryForPage(queryBuilder.build(), Rgoods.class); //需要显示的数据 rs.setRgoods( rgoods.getContent()); rs.setCurrentPage(rgoods.getNumber()); rs.setTotal((int)rgoods.getTotalElements()); rs.setPageSize(rgoods.getSize()); return rs; } }
24. web
package com.los.es.web; import com.los.es.config.RequestResult; import com.los.es.config.ResponseResult; import com.los.es.service.GoodsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class RgoodsController { @Autowired private GoodsService goodsService; @GetMapping("find") public ResponseResult find(RequestResult requestResult){ return goodsService.findByKey(requestResult); } }
25.前端使用比较简陋,使用vue实现。首先创建vue项目,引入ElementUi和axios。单页面就直接贴代码了
<template> <div class="hello"> <input v-on:input="inputFun" placeholder="搜索" type="text" @keyup.enter="searchEnterFun" size="mini" v-model="search"> <el-select v-model="value" multiple filterable remote reserve-keyword placeholder="请输入关键词" :remote-method="remoteMethod" :loading="loading"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> <el-table v-loading="loading" :data = "tableData" style="width: 100%"> <el-table-column label="level" prop="date"> </el-table-column> <el-table-column label="Name" prop="name"> </el-table-column> <el-table-column align="right"> <template slot="header" slot-scope="scope"> </template> </el-table-column> </el-table> <!-- 分页 --> <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[20, 30, 40, 50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination> </div> </template> <script> const axios = require("axios"); export default { name: ‘HelloWorld‘, data () { return { options: [], value: [], list: [], states: [], tishiloading:false, loading:false, currentPage:0,// 当前页码 pageSize:0,// 每页大小 total:0, //总条数 ,以上值在初始化时赋予 tableData: [], search: ‘‘ } }, created() { this.init() }, methods: { init: function(h) { //alert("初始化信息") var app=this; var a=h==undefined?app:h console.log(‘init‘) axios .get("http://localhost:8888/find") .then(function(response) { a.states = response.data.rgoods a.list = a.states.map(item => { return { value: item.name, label: item.name }; }); a.tableData = response.data.rgoods a.total = response.data.total a.pageSize = response.data.pageSize a.currentPage = response.data.currentPage }) .catch(function(error) { console.log(error); }); }, //但用户输入时触发函数 inputFun(){ var vm = this vm.loading = true }, //回车事件 searchEnterFun(){ var vm = this axios .get("http://localhost:8888/find",{ params:{ size:vm.pageSize, page:vm.pageNumber, searchKey:vm.search } }).then(function(response){ vm.tableData = response.data.rgoods vm.total = response.data.total vm.pageSize = response.data.pageSize vm.pageNumber = response.data.pageNumber vm.loading =false }).catch(function(error){ console.log(error) }) }, //长度改变----改变每页显示的条数的时候 自动触发 handleSizeChange(val){ var vm = this console.log("长度改变:"+val+"--当前页"+vm.currentPage) axios .get("http://localhost:8888/find",{ params:{ size:val, page:vm.pageNumber, searchKey:vm.search } }).then(function(response){ vm.tableData = response.data.rgoods vm.total = response.data.total vm.pageSize = response.data.pageSize }).catch(function(error){ console.log(error) }) }, // 当前改变----当前页码改变之后(上下页),触发这个函数 handleCurrentChange(val){ var vm = this console.log("当前改变:"+val+"每页显示条数"+vm.pageSize) axios .get("http://localhost:8888/find",{ params:{ page:val, size:vm.pageSize, searchKey:vm.search } }) .then(function(response) { vm.tableData = response.data.rgoods vm.total = response.data.pageInfo.total vm.pageSize = response.data.pageInfo.pageSize vm.currentPage = response.data.currentPage }) .catch(function(error) { console.log(error); }); }, }, } </script> <style scoped> </style>
以上是关于springBoot+Window下的Elasticsearch实现查询的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot2.x集成分布式搜索引擎Elasticsearch
Elasticsearch7.8.0版本入门——JavaAPI操作(环境准备)
Elasticsearch7.8.0版本入门——JavaAPI操作(环境准备)