使用es完成前端查询功能

效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一:将数据库数据同步到es

1.首先在数据库选择需要的资源条件,将sql语句执行出来
在这里插入图片描述
2.将sql语句放入es的sync_tanle.cfg配置文件执行
在这里插入图片描述
3.修改index名称
在这里插入图片描述
sync_tanle.cfg文件完成版

input {
  jdbc {
     # mysql相关jdbc配置
    jdbc_connection_string => "jdbc:mysql://192.168.230.1:3306/ddd?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"
    jdbc_user => "root"
    jdbc_password => "123123"

    # jdbc连接mysql驱动的文件, 此处路径一定要正确 否则会报com.mysql.cj.jdbc.Driver could not be loaded
    jdbc_driver_library => "/opt/logstash-7.7.0/config/sync/mysql-connector-java-8.0.13.jar"
    jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
    jdbc_paging_enabled => true
    jdbc_page_size => "50000"

    jdbc_default_timezone =>"Asia/Shanghai"
    # mysql文件, 也可以直接写SQL语句在此处,如下:
    statement => "SELECT
	 	p.id,
		p.`name`,
		p.brand_name,
		p.product_category_name,
		p.publish_status,
		p.new_status,
		p.sub_title,
		ps.sku_code,
		ps.price,
		p.pic,
		ps.sale,
		ps.sp_data 
	           FROM
		pms_product p
	          LEFT JOIN pms_sku_stock ps 
	        ON p.id = ps.product_id
                           GROUP BY p.`name`"

   # 这里类似crontab,可以定制定时操作,比如每分钟执行一次同步(分 时 天 月 年)
    schedule => "* * * * *"
 
    # 是否需要记录某个column 的值,如果record_last_run为真,可以自定义我们需要 track 的 column 名称,此时该参数就要为 true. 否则默认 track 的是 timestamp 的值.
    use_column_value => true

   # 如果 use_column_value 为真,需配置此参数. track 的数据库 column 名,该 column 必须是递增的. 一般是mysql主键
    tracking_column => "create_time"

    tracking_column_type => "timestamp"

    last_run_metadata_path => "area_logstash_capital_bill_last_id"

    # 是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
    clean_run => false

#是否将 字段(column) 名称转小写
    #lowercase_column_names => false
  }
}

filter {
  date {
    match => [ "create_time", "yyyy-MM-dd HH:mm:ss" ]
    timezone => "Asia/Shanghai"
  }
}

output {
  elasticsearch {
   #虚拟机id
    hosts => ["192.168.230.134:9200"]
     # index名 自定义 相当于数据库 对于实体类上@Document(indexName = "jq_product")indexName
    index => "jq_product"  
 #需要关联的数据库中有有一个id字段,对应索引的id号
    document_id => "%{id}"
    template_overwrite => true
  }

  stdout {
      codec => json_lines
  }
}

4.开始同步 在/opt/logstash-7.7.0/bin/目录里
在这里插入图片描述

[root@localhost bin]# ./logstash -f /opt/logstash-7.7.0/config/sync/sync_tanle.cfg

注意: 如果重新执行同步先查询进程,杀死之前的进程

[root@localhost bin]# ps -ef | grep logstash
在这里插入图片描述
[root@localhost bin]# kill -9 5388

5.效果:
在这里插入图片描述
二:创建springboot项目开始完成代码:
1.配置文件
application.yml

spring:
  application:
  	#项目名称
    name: jq-search
  elasticsearch:
    rest:
    #连接es
      uris: http://192.168.230.134:9200

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#端口号
server:
  port: 5053
#连接服务中心
eureka:
  client:
    service-url:
      defaultZone: http://localhost:5051/eureka

创建实体类

package com.jq.model;

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

@Data
@Document(indexName = "j_product")//连接es
public class SerchModel {
   private Long id;
   @Field(type = FieldType.Text,analyzer = "ik_max_word")
   private String name;
    @Field(type = FieldType.Text)
    private String brand_name;
    @Field(type = FieldType.Text)
    private String product_category_name;
    @Field(type = FieldType.Text)
    private String publish_status;
    @Field(type = FieldType.Text)
    private String new_status;
    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String sub_title;
    @Field(type = FieldType.Text)
    private String sku_code;
    @Field(type = FieldType.Text)
    private String price;
    @Field(type = FieldType.Text)
    private String pic;
    @Field(type = FieldType.Text)
    private String sale;
    @Field(type = FieldType.Text)
    private String sp_dat;
}

创建分页PageBean类

package com.jq.page;

import lombok.Data;

import java.util.List;

@Data
public class PageBean<T> {

    private Integer page;
    private Integer size;
    private Long total;
    private List<T> data;


}

创建ProductSearch类,相当于vo

package com.jq.search;


import com.jq.page.PageBean;
import lombok.Data;

@Data
public class ProductSearch extends PageBean {
    private String key;
}

创建统一返回值类

package com.jq.result;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultObj {

    // 状态码
    private Integer code;

    // 信息
    private String msg;

    // 数据
    private Object data;

    public ResultObj(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static ResultObj success(){
        return new ResultObj(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
    }

    public static ResultObj success(Object data){
        return new ResultObj(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), data);
    }

    public static ResultObj error(ResultCode resultCode){
        return new ResultObj(resultCode.getCode(), resultCode.getMsg(),null);
    }


}

创建code码枚举类

package com.jq.result;


public enum ResultCode {

    SUCCESS(200,"操作成功"),
    ERROR(500,"操作失败"),
    USERNAME_PASSWORD_ISNULL(1001,"用户名或密码为空"),
    USER_NOEXIST(1002,"用户不存在"),
    PASSWORD_ERROR(1003,"密码错误"),
    TOKEN_ERROR(1004,"身份过期,请重新登录"),
    NO_PERMISSION(403,"没有权限访问该方法"),
    PHONE_NULL(1005,"手机号为空"),
    GET_CODE_ERROR(1006,"获取验证码失败"),
    PHONE_CODE_ISBULL(1007,"手机号码或验证码不能为空"),
    CODE_ERROR(1008,"验证码错误"),
    PHONE_CODE_TIMEOUT(1009,"手机号码不正确或验证码过期")
    ;

    private Integer code;
    private String msg;

    ResultCode(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

开始实现代码:
controller控制器

package com.jq.controller;

import com.jq.result.ResultObj;
import com.jq.search.ProductSearch;
import com.jq.service.SearchProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin//跨域
@RequestMapping("search")
public class SearchController {

    @Autowired
    private SearchProductService searchProductService;

    @GetMapping
    public ResultObj getSearchProduct(ProductSearch productSearch){
        ProductSearch search= searchProductService.searchProduct(productSearch);
        return ResultObj.success(search);
    }




}

SearchProductServiceImpl 实现类代码:

package com.jq.service.impl;

import com.jq.model.SerchModel;
import com.jq.search.ProductSearch;
import com.jq.service.SearchProductService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

@Service
public class SearchProductServiceImpl implements SearchProductService {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public ProductSearch searchProduct(ProductSearch productSearch) {
        if(StringUtils.isBlank(productSearch.getKey())){
            //用户不选择查询数据,设置查询的默认值
            productSearch.setKey("手机");
        }

        //构建分页
        Pageable pageable= PageRequest.of(productSearch.getPage(),productSearch.getSize());
        NativeSearchQueryBuilder builder=new NativeSearchQueryBuilder();
        NativeSearchQuery query=builder.withQuery(QueryBuilders.queryStringQuery(productSearch.getKey()))
                .withPageable(pageable)
                .build();
        SearchHits<SerchModel> search = elasticsearchRestTemplate.search(query, SerchModel.class);
        Stream<SearchHit<SerchModel>> searchHitStream = search.get();
        List<SerchModel>list=new ArrayList<>();
        searchHitStream.forEach(searchHit->{
            list.add(searchHit.getContent());
        });
        productSearch.setData(list);
        productSearch.setTotal(search.getTotalHits());
        return productSearch;
    }

}

三:前端代码:

<template>
  <div>
    <div class="house-header">
      <div class="layui-container">
        <div class="house-nav">
      <span class="layui-breadcrumb" lay-separator="|">
        <a href="login.html">登录</a>
        <a href="">我的订单</a>
        <a href="">在线客服</a>
      </span>
          <span class="layui-breadcrumb house-breadcrumb-icon" lay-separator=" ">
        <a id="search"><i class="layui-icon layui-icon-house-find"></i></a>
        <a href="login.html"><i class="layui-icon layui-icon-username"></i></a>
        <a href="usershop.html"><i class="layui-icon layui-icon-house-shop"></i></a>
      </span>
        </div>
        <div class="house-banner layui-form">
          <a class="banner" href="index.html">
            <img src="../../../static/static/img/banner.png" alt="家居商城">
          </a>
          <div class="layui-input-inline">
            <input type="text" placeholder="搜索好物" class="layui-input"><i class="layui-icon layui-icon-house-find"></i>
          </div>
          <a class="shop" href="usershop.html"><i class="layui-icon layui-icon-house-shop"></i><span class="layui-badge">1</span></a>
        </div>
        <ul class="layui-nav close">
          <li class="layui-nav-item layui-this"><a href="index.html">首页</a></li>
          <li class="layui-nav-item"><a href="list.html">居家用品</a></li>
          <li class="layui-nav-item"><a href="list.html">小家电</a></li>
          <li class="layui-nav-item"><a href="list.html">洗护</a></li>
          <li class="layui-nav-item"><a href="list.html">厨具</a></li>
          <li class="layui-nav-item"><a href="list.html">日用品</a></li>
        </ul>
        <button id="switch">
          <span></span><span class="second"></span><span class="third"></span>
        </button>
      </div>
    </div>

    <div class="layui-container house-list">
      <p class="classify"><a href="index.html">首页</a> &gt; <span>家居用品</span></p>
      <div class="list-banner"></div>
      <div class="filter">
        <div><span>分类:</span><ul><li class="active">全部</li><li>床品</li><li>灯具</li><li>布艺</li><li>收纳</li><li>小家具</li></ul></div>
        <div><span>季节:</span><ul><li class="active">全部</li><li></li><li></li><li></li><li></li></ul></div>
        <div><span>排序:</span><ul><li class="active">默认</li><li>价格<i class="layui-icon layui-icon-house-up"></i><i class="layui-icon layui-icon-triangle-d"></i></li><li>上架时间</li></ul></div>
      </div>
      <div class="layui-row layui-col-space25">
        <div class="layui-col-xs6 layui-col-sm3" v-for="product in dataList">
          <div class="list-detail" >
            <div class="img"><img :src="product.pic"></div>
            <p class="title"><a href="detail.html">{{product.sub_title}}</a></p>
            <p><span class="price">{{product.price}}</span><span>1266</span>人付款</p>
          </div>
        </div>
      </div>
      <div style="text-align: center">
        <el-pagination
          background
          layout="total, prev, pager, next,jumper"
          :current-page="query.page+1"
          :page-size="query.size"
          :total="total"
          @current-change="handleCurrentChange"
        ></el-pagination>
      </div>
    </div>

    <div class="house-footer">
      <div class="layui-container">
        <div class="intro">
          <span class="first"><i class="layui-icon layui-icon-house-shield"></i>7天无理由退换货</span>
          <span class="second"><i class="layui-icon layui-icon-house-car"></i>99元全场包邮</span>
          <span class="third"><i class="layui-icon layui-icon-house-diamond"></i>100%品质保证</span>
          <span class="last"><i class="layui-icon layui-icon-house-tel"></i>客服400-2888-966</span>
        </div>
        <div class="about">
      <span class="layui-breadcrumb" lay-separator="|">
        <a href="about.html">关于我们</a>
        <a href="about.html">帮助中心</a>
        <a href="about.html">售后服务</a>
        <a href="about.html">配送服务</a>
        <a href="about.html">关于货源</a>
      </span>
          <p>家居商城版权所有 &copy; 2012-2020</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import {getSearchProduct} from "../../api/Product/product";

  export default {
      name: "ProductList",
      data(){
        return{
          dataList:[],
          total:null,
          query:{
            page:0,
            size:10,
            key:""
          }
        }
      },
      methods:{
        //从es查询数据
        getList(){
          getSearchProduct(this.query).then(result =>{
            this.dataList=result.data.data.data;
            this.total=result.data.data.total;
          })
        },
        // 分页导航
        handleCurrentChange(val) {
          this.$set(this.query, 'page', val-1);
          this.getList();
        },
    
      },
      created() {
        //初始化
        this.getList(),
        layui.config({
          base: '../../../../static/static/js/'
        }).use('house');
      },
    }
</script>

<style scoped>

</style>

product.js发起请求

import request from '../../utils/request';


//从es取数据商品
export const getSearchProduct = query => {
    return request({
        url: 'http://localhost:5053/search/',
        method: 'get',
        params: query
    });
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jq1223

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值