大家好,今天突发奇想,,学习拉一下Elasticsearch,今天来跟大家分享一下,平时不熬夜得的我,最近熬夜搞这个东西,可能不是那么完美,也会有小bug,所以请大家谅解
去官网下载https://www.elastic.co/cn/downloads/elasticsearch
下面运行Elasticsearch
下载完解压即可:直接双击/bin/ElasticSearch.bat
运行成功之后,就在浏览器输入http://localhost:9200
如图所示;
这里不做详情解说哦;
然后我们:
同样输入框:cmd 到该目录
输入命令 npm install 回车执行
输入 npm run start 启动服务
这样之后在浏览器中输入:http://localhost:9100 查看
下载地址:https://www.elastic.co/downloads/logstash
解压压缩包之后我们就连接数据库
logstash-mysql.conf 文件内容
input {
stdin {
}
#如果需要同步多个表,那么重复配置jdbc{}这一部分,只需要修改表相关的部分
jdbc {
# 数据库 数据库名称为test,表名为users
jdbc_connection_string => "jdbc:mysql://localhost:3306/elasticsearch"
# 用户名密码
jdbc_user => "root"
jdbc_password => "******"
# jar包的位置(把jar包直接放到logstash-core/lib/jars下)
jdbc_driver_library => "E:\logstash-7.4.2\logstash-core\lib\jars\mysql-connector-java-5.1.39-bin.jar"
# mysql的Driver
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
#statement_filepath => "config-mysql/book.sql"
#这里的sql效果是:全量同步、增量更新users表。 如果需要全量同步以及更新users表,则select * from users即可。
statement => "select * from car"
#定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新(cron表达式)
schedule => "* * * * *"
#索引的类型
type => "_doc"
}
}
filter {
json {
source => "message"
remove_field => ["message"]
}
}
output {
elasticsearch {
hosts => "127.0.0.1:9200"
# index名
index => "goods"
# 需要关联的数据库中要有一个id字段(最好就是表的主键),对应索引的id号
document_id => "%{cid}"
}
stdout {
codec => json_lines
}
}
切记,有些东西改成自己;然后这个conf放在logstash-7.4.2中bin目录下
现在我们打开cmd,在框中输入grunt server 就会发现会报错,这个时候,输入cmd 输入 npm install -g grunt-cli (建议在logstash-7.4.2中打开cmd)
然后再输入grunt -version
出现版本说明成功啦
config里面的代码上两篇文件已经分享过,可以去上文copy
application.yml
server:
port: 8989
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 127.0.0.1:9300
jackson:
default-property-inclusion: non_null
datasource:
url: jdbc:mysql://127.0.0.1:3306/elasticsearch?useSSL=false
username: root
password: ******
driver-class-name: com.mysql.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
pojo层
goods:
package com.demo.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 = "goods", type = "_doc", shards = 1, replicas = 0)
public class Goods {
@Id
private Long cid;
// @Field(type = FieldType.Keyword, analyzer = "ik_max_word")
// private String all; // 所有需要被搜索的信息,包含标题,分类,甚至品牌
@Field(type = FieldType.Keyword, index = true, analyzer = "ik_max_word")
private String name;
@Field(type = FieldType.Keyword)
private String isParent;
@Field(type = FieldType.Keyword)
private String parentId;
@Field(type = FieldType.Keyword)
private Long level;
@Field(type = FieldType.Keyword)
private String pathid;
@Field(type = FieldType.Keyword, index = true, analyzer = "ik_max_word")
private String path;
}
Xcgoods
package com.demo.elasticsearch.pojo;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
@Data
@Entity(name="car")
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;
}
SearchRequest.java
package com.demo.elasticsearch.pojo;
public class SearchRequest {
private String key;// 搜索条件
private Integer page;// 当前页
private static final Integer DEFAULT_SIZE = 20;// 每页大小,不从页面接收,而是固定大小
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;
}
}
SearchResult.java
package com.demo.elasticsearch.pojo;
import com.demo.elasticsearch.utils.PageResult;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class SearchResult extends PageResult {
public SearchResult() {
}
public SearchResult(Long total, Long totalPage, List items) {
super(total,totalPage,items);
}
}
下面是Dao层代码
GoodsRepository.java
package com.demo.elasticsearch.repository;
import com.demo.elasticsearch.pojo.Goods;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface GoodsRepository extends ElasticsearchRepository {
}
XcGoodsRepository.java
package com.demo.elasticsearch.repository;
import com.demo.elasticsearch.pojo.Goods;
import com.demo.elasticsearch.pojo.XcGoods;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface XcGoodsRepository extends JpaRepository, JpaSpecificationExecutor {
}
Service层
SearchService.java
package com.demo.elasticsearch.service;
import com.demo.elasticsearch.pojo.Goods;
import com.demo.elasticsearch.pojo.SearchRequest;
import com.demo.elasticsearch.pojo.XcGoods;
import com.demo.elasticsearch.utils.PageResult;
public interface SearchService {
Goods buildGoods(XcGoods goods);
PageResult search(SearchRequest request);
}
下面实现我们的service层
package com.demo.elasticsearch.service.impl;
import com.demo.elasticsearch.pojo.Goods;
import com.demo.elasticsearch.pojo.SearchRequest;
import com.demo.elasticsearch.pojo.SearchResult;
import com.demo.elasticsearch.pojo.XcGoods;
import com.demo.elasticsearch.repository.GoodsRepository;
import com.demo.elasticsearch.service.SearchService;
import com.demo.elasticsearch.utils.PageResult;
import lombok.extern.slf4j.Slf4j;
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.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import java.util.List;
@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.setPath(xcgoods.getPath());
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);
}
}
util包
package com.demo.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;
}
}
最后就是我们的controller层
package com.demo.elasticsearch.web;
import com.demo.elasticsearch.pojo.Goods;
import com.demo.elasticsearch.pojo.SearchRequest;
import com.demo.elasticsearch.service.SearchService;
import com.demo.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.RestController;
@RestController
public class SearchController {
@Autowired
private SearchService searchService;
/**
* 搜索功能
* @param request
* @return
*/
@GetMapping("search")
public ResponseEntity> search(SearchRequest request) {
return ResponseEntity.ok(searchService.search(request));
}
}
到这里我们的后台代码就结束啦
下面分享我的前台,,我前台代码是Vue写的,可以参考,我写啦两种方式
第一种方式就是,我有一个表格,有一个搜索框,点击查询之后将数据显示在表格中:
查询
Edit
Delete
这种的话就比较传统,可以参考这种,但是我这里有个问题就是我只能显示id和name,所以可能要根据自己的字段个数对table做增减
还有一种就是我在搜索框内输入文字,然后他实时显示,将他显示在下拉框:
这个的话就比较新奇吧,可根据个人爱好选择哪一个方式