ElasticSearch学习

ElasticSearch

简称es

高扩展的分布式全文检索引擎;实时的存储、检索数据

基于java开发

ElasticSearch安装

解压就可以使用了!

目录

  • bin 启动文件
  • config 配置文件
    • log4j2 日志配置文件
    • jvm.options java虚拟机相关的配置
    • elasticsearch.yml elasticsearch的配置文件 默认端口9200 跨域
  • lib 相关的jar包
  • logs 日志
  • modules 功能模块
  • plugins 插件 ik

启动

双击bin目录下的elasticsearch.bat

默认访问9200,通讯9300

访问测试:

image-20220302170746989

安装可视化界面 es head的插件

数据视图展示工具,后续查询用kibana

github有下载地址,太慢了没打开 = =, 需要前端

npm install

npm run start

此时访问 http://localhost:9100/,但是要解决跨域问题

解决跨域问题

在elasticsearch.yml中加上这个,重启服务即可解决

http.cors.enabled: true
http.cors.allow-origin: "*"
创建索引

如果报错就重启服务即可

可以把es当作一个数据库,可以建立索引(库),文档(库中的数据)

image-20220303093423097

安装kibana

官网下载,拆箱即用

启动测试

默认端口:http://localhost:5601

image-20220303094437998
访问测试
image-20220303094713672 image-20220303094951924
汉化
image-20220303095257361

ElasticSearch概念

面向文档, 一切都是JSON

Relational DBElasticSearch
数据库(database)索引(indeices == 数据库)
表(tables)types
行(rows)document(文档==记录)
字段(columns)fields

IK分词器

中文分词器使用IK

把一段段中文划分成一个个的关键字

  • 最少切分 ik_smart
  • 最细粒度划分 il_max_word

下载安装

解压到 ElasticSearch的插件中,全部关了重启观察es

image-20220303102156216

加载插件

查看加载进来的插件

elasticsearch-plugin list

image-20220303102812014

使用kibana测试

启动kibana

查看不同的分词器

  • 最少切分 ik_smart
    • image-20220303103302097
  • 最细粒度划分 ik_max_word(穷尽词库,根据字典)

发现问题,输入字典没有的词,需要的词汇被拆开

这种自己需要的词,需要自己加到分词器的字典中

ik分词器增加自己的配置

增加配置后重启es

image-20220303104158361

加载到了!

image-20220303104513386

image-20220303104638778

Rest风格

image-20220303104832919

索引的基本操作

1、创建一个索引

三个工具都打开

PUT /索引名/(类型名)/文档id
{
请求体
}
PUT /test1/type1/1
{
  "name": "蒋二妹",
  "age": 3
}
image-20220306220845751
  • 完成了自动增加的索引,数据也成功的添加了
image-20220306220958627

2、指定字段的类型

创建规则,以后放数据

image-20220306221402984 image-20220306221501664

获取规则

GET test2

{
  "test2" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "long"
        },
        "birthday" : {
          "type" : "date"
        },
        "name" : {
          "type" : "text"
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1646576023965",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "ga5mzX7YQFG6GsfzOXohVA",
        "version" : {
          "created" : "7060199"
        },
        "provided_name" : "test2"
      }
    }
  }
}

查看默认的信息

image-20220306221959896

如果文档字段没有指定,es会默认配置字段类型

通过GET _cat/****可以获取更多信息

3、修改一个索引

使用PUT,直接覆盖(这个是以前的方法)

image-20220306222447629

使用post

POST /test3/_doc/1/_update
{
  "doc": {
    "name": "蒋二妹QAQ"
  }
}
image-20220306222724110

4、删除一个索引

根据请求来判断的

DELETE test1

文档的基本操作*

基本操作

  1. 添加数据
PUT /jq/user/1
{
  
  "name": "蒋二妹",
  "age": 22,
  "desc": "很穷",
  "tags": ["女", "穷"]
}
image-20220306223510154
  1. 获取数据 PUT
GET jq/user/1
  1. 更新数据
PUT /jq/user/3
{
  
  "name": "李四233",
  "age": 4,
  "desc": "mmap",
  "tags": ["男", "穷"]
}
  1. 更新数据 POST /_update
post /jq/user/3/_update
  1. 简单的搜索
GET /jq/user/3

加条件

GET jq/user/_search?q=name:张三

匹配度越高分值越高

image-20220306225016654

  1. 复杂的搜索

复杂操作(搜索)

排序、分页、高亮、模糊查询,精准查询

GET jq/user/_search
{  //参数体
  "query": {
    "match": {
      "name": "张三"
    }
  }
}
image-20220306225504463
  • 年龄、名字、减少输出结果
GET jq/user/_search
{
  "query": {
    "match": {
      "name": "张三"
    }
  }
  , "_source": ["name", "desc"]  //结果的过滤==select name, desc from ...
}
image-20220306225647179
  • 排序
GET jq/user/_search
{
  "query": {
    "match": {
      "name": "张三"
    }
  },
 "sort": [
   {
     "age": {
       "order": "desc"
     }
   }
 ]
}
  • 分页
GET jq/user/_search
{
  "query": {
    "match": {
      "name": "张三"
    }
  },
 "sort": [
   {
     "age": {
       "order": "desc"
     }
   }
 ],
 "from": 0,
 "size": 1  //大小
}
  • 布尔查询

must:多条件查询 === where name = xx and age = xx

GET jq/user/_search
{
  "query": {
   "bool": {
     "must": [
       {
          "match": {
            "name": "张三"
    }
       },
       {
         "match": {
           "age": 3
         }
       }
     ]
   }
  }
}

should:多条件查询 === where name = xx or age = xx

  • 过滤器
GET jq/user/_search
{
  "query": {
   "bool": {
     "must": [
       {
          "match": {
            "name": "张三"
          }
       }
     ],
     "filter": {
       "range": {
         "age": {
           "gte": 0,  //大于等于   gt:大于
           "lte": 10  //小于等于   lt:小于
         }
       }
     }
   }
  }
}
  • 匹配多个条件
GET jq/user/_search
{
  "query": {
    "match": {
      "tags": "男 穷"
    }
  }
}
//多个条件使用空格  只要满足一个就可以被查出
  • 精确查询

    • 关于分词

      • term 通过倒排索引指定的词条进行精确的查找,当成整体

        • GET jq/user/_search
          {
            "query": {
              "term": {
                "name": "张"
              }
            }
          }
          
      • match 会拆分

  • 高亮

GET jq/user/_search
{
  "query": {
    "match": {
      "name": "张三"
    }
  },
  "highlight": {
    "fields": {
      "name": {}
    }
  }
}



image-20220306232450921

image-20220306232917300

集成SpringBoot

找文档:java rest client 使用高级客户端

  1. 找到原生的依赖

  2. 找到类

  3. 分析方法

创建项目

创建类

package com.jiang.config;

//找对象
//放到springboot中待用
@Configuration  //相比于xml
public class ElasticSearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        //保证本地的es开启状态
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")
                )
        );
        return client;
    }
}

测试1(索引的API基操)

@SpringBootTest
class EsApiApplicationTests {

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    /**
     * 创建索引
     * @throws IOException
     */
    @Test
    void testCreateIndex() throws IOException {
        //1.创建索引请求
        CreateIndexRequest request = new CreateIndexRequest("jq");
        //2.执行请求,请求后获得响应
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(response);
    }

    /**
     * 获取,只能判断是否存在
     * @throws IOException
     */
    @Test
    void testGetIndex() throws IOException {
        GetIndexRequest request = new GetIndexRequest("jq");
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);  //true
    }

    /**
     * 删除索引
     * @throws IOException
     */
    @Test
    void testDeleteIndex() throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest("jq");
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());  //true
    }
}

测试2(文档的API基操)

1. 新建实体类

package com.jiang.pojo;

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

/**
 * @author 蒋二妹QAQ
 * @date 2022/3/23
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;

    private int age;
}

2. 测试

@SpringBootTest
class EsApiApplicationTests {

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    /**
     * 测试添加文档
     */
    @Test
    public void testAddDocument() throws IOException {
        //创建对象
        User user = new User("蒋二妹", 3);
        //1.创建请求   如果此时没有这个索引,就要先创建索引
        IndexRequest request = new IndexRequest("jq");

        //规则 put/jq/1
        request.id("1");
        request.timeout(TimeValue.timeValueSeconds(1));
        //request.timeout("1s");

        //2.将数据放入请求之中,数据都是json数据哦  --需要引入阿里巴巴的fastjson
        IndexRequest source = request.source(JSON.toJSONString(user), XContentType.JSON);  //不用拿请求也是可以的

        //3.客户端发送请求,获取响应结果
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);

        System.out.println(indexResponse.toString());
        System.out.println(indexResponse.status());  //CREATE
    }

    /**
     * 获取文档,判断是否存在 get /index/doc/1
     */
    @Test
    public void textIsExists() throws IOException {
        GetRequest getRequest = new GetRequest("jq", "1");
        //不获取返回的 _source 的上下文
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields("_none_");

        boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    /**
     * 获取文档信息
     */
    @Test
    public void testGetDocument() throws IOException {
        GetRequest getRequest = new GetRequest("jq", "1");
        GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsString());  //打印文档的内容 {"age":3,"name":"蒋二妹"}
        System.out.println(response);  //返回全部
    }

    /**
     * 更新文档的信息
     */
    @Test
    public void testUpdateDocument() throws IOException {
        UpdateRequest updateRequest = new UpdateRequest("jq", "1");
        updateRequest.timeout("1s");

        User user = new User("蒋二妹QAQ", 11);
        updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);

        UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(updateResponse.status());
    }

    /**
     * 删除文档记录
     */
    @Test
    public void testDeleteDocument() throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest("jq", "1");
        deleteRequest.timeout("1s");

        DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }

    /**
     * 批量插入数据
     */
    @Test
    public void testBulkRequest() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("1s");

        ArrayList<User> userList = new ArrayList<>();
        userList.add(new User("张三1", 1));
        userList.add(new User("张三2", 2));
        userList.add(new User("张三3", 3));
        userList.add(new User("张三4", 4));
        userList.add(new User("张三5", 5));
        userList.add(new User("张三6", 6));

        //批处理请求
        for (int i = 0; i < userList.size(); i++) {
            //批量更新和删除,在这里修改对应的请求
            bulkRequest.add(
                    new IndexRequest("jq")
                            .id("" + (i + 2))  //不设置的话就是随机
                            .source(JSON.toJSONString(userList.get(i)), XContentType.JSON)
            );
        }

        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkResponse.hasFailures());  //false  没有失败
    }

    /**
     * 查询
     * searchRequest  搜索请求
     * SearchSourceBuilder  条件构造
     * highlightBuilder  高亮
     * TermQueryBuilder  精确查询
     */
    @Test
    public void testSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("jq");
        //1. 构建搜索的条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //QueryBuilders 快速实现设置查询条件
        //QueryBuilders.termQuery()   精确匹配
        //QueryBuilders.matchAllQuery()  匹配所有
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "张三1");//精确查询
        //MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();

        //构造器
        sourceBuilder.query(termQueryBuilder);
        //分页
        //sourceBuilder.from();
        //sourceBuilder.size();
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        //2. 放到请求里面
        searchRequest.source(sourceBuilder);

        //3. 发送请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(searchResponse.getHits()));
        System.out.println("======================================");
        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
            System.out.println(documentFields.getSourceAsMap());
        }
    }
}

**实战

新建好一个springboot web的项目后,准备好前端资料

爬虫

数据问题:

  • 数据库获取
  • 消息队列中获取
  • 爬虫获取

都可以成为数据源

爬取数据:(获取请求返回的信息,筛选出想要的数据)

导入jsoup包

 <!--解析网页-->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.10.2</version>
</dependency>

爬虫工具类

HtmlParseUtil

package com.jiang.utils;

/**
 * @author 蒋二妹QAQ
 * @date 2022/3/23
 **/
@Component
public class HtmlParseUtil {

    //public static void main(String[] args) throws IOException {
    //    new HtmlParseUtil().parseJD("java").forEach(System.out::println);
    //}

    public List<Content> parseJD(String keywords) throws IOException {
        String url = "https://search.jd.com/Search?keyword=" + keywords;
        Document document = Jsoup.parse(new URL(url), 30000);
        Element element = document.getElementById("J_goodsList");
        Elements elements = element.getElementsByTag("li");
        ArrayList<Content> goodsList = new ArrayList<>();

        for (Element el : elements) {
            String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img");
            String price = el.getElementsByClass("p-price").eq(0).text();
            String title = el.getElementsByClass("p-name").eq(0).text();
            Content content = new Content();
            content.setTitle(title);
            content.setPrice(price);
            content.setImg(img);
            goodsList.add(content);
        }
        return goodsList;
    }
}


/*
        //获取请求  https://search.jd.com/Search?keyword=java
        String url = "https://search.jd.com/Search?keyword=java";

        //解析网页,原生API  (返回的document就是js页面对象)
        Document document = Jsoup.parse(new URL(url), 30000);

        //所有在js中使用的方法这里都能用
        Element element = document.getElementById("J_goodsList");
        //System.out.println(element.html());

        //获取所有的li元素
        Elements elements = element.getElementsByTag("li");

        //这里的el就是每一个li标签了
        for (Element el : elements) {
            //关于图片特别多的网站,图片是懒加载--延迟加载的
            // 应该是 source-data-lazy-img
            String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img");
            String price = el.getElementsByClass("p-price").eq(0).text();
            String title = el.getElementsByClass("p-name").eq(0).text();

            System.out.println("======================================");
            System.out.println(img);
            System.out.println(price);
            System.out.println(title);
        }

 */

实体类

package com.jiang.pojo;

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

import java.math.BigDecimal;

/**
 * @author 蒋二妹QAQ
 * @date 2022/3/23
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
    private String img;

    private String price;

    private String title;
}

客户端

package com.jiang.config;

//找对象
//放到springboot中待用
@Configuration  //相比于xml
public class ElasticSearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        //保证本地的es开启状态
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")
                )
        );
        return client;
    }
}

controller

package com.jiang.controller;

/**
 * 请求
 *
 * @author 蒋二妹QAQ
 * @date 2022/3/23
 **/
@RestController
public class ContentController {

    @Autowired
    private ContentService contentService;

    /**
     * 解析数据放到 es索引库中
     *
     * @param keyword
     * @return
     * @throws Exception
     */
    @GetMapping("/parse/{keyword}")
    public boolean parse(@PathVariable("keyword") String keyword) throws Exception {
        return contentService.parseContent(keyword);
    }

    @GetMapping("/search/{keyword}/{pageNum}/{pageSize}")
    public List<Map<String, Object>> search(@PathVariable("keyword") String keyword,
                                            @PathVariable("pageNum") int pageNum,
                                            @PathVariable("pageSize") int pageSize) throws IOException {
        return contentService.searchPage(keyword, pageNum, pageSize);
    }
}

service

package com.jiang.service;

/**
 * 业务
 *
 * @author 蒋二妹QAQ
 * @date 2022/3/23
 **/
@Service
public class ContentService {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 1. 解析数据放到 es索引库中
     *
     * @param keywords
     * @return
     * @throws Exception
     */
    public boolean parseContent(String keywords) throws Exception {
        List<Content> contents = new HtmlParseUtil().parseJD(keywords);

        //查询出来的数据放入到es中,批量添加
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("2m");

        for (int i = 0; i < contents.size(); i++) {
            bulkRequest.add(new IndexRequest("jd_goods")
                    .source(JSON.toJSONString(contents.get(i)), XContentType.JSON));
        }

        BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        return !bulk.hasFailures();
    }

    /**
     * 2. 获取这些数据实现基本搜索功能
     *
     * @param keyword
     * @param pageNum
     * @param pageSize
     * @return
     * @throws IOException
     */
    public List<Map<String, Object>> searchPage(String keyword, int pageNum, int pageSize) throws IOException {
        if (pageNum < 1) {
            pageNum = 1;
        }

        // 条件搜索
        SearchRequest searchRequest = new SearchRequest("jd_goods");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 分页
        sourceBuilder.from(pageNum);
        sourceBuilder.size(pageSize);

        // 精准匹配关键字
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        // 高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        highlightBuilder.requireFieldMatch(false);   //多个关键字高亮  --false
        sourceBuilder.highlighter(highlightBuilder);

        // 执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        // 解析结果
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {

            // 解析高亮的字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            if (title != null) {
                Text[] fragments = title.fragments();
                String newTitle = "";
                for (Text text : fragments) {
                    newTitle += text;
                }
                sourceAsMap.put("title", newTitle);   //返回到map里面生效
            }

            list.add(sourceAsMap);
        }
        return list;
    }
}

前后端分离

新建一个文件夹

npm init

npm install

npm install vue

npm install axios

主要是把js放到static下

image-20220323164201666

使用VUE

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="utf-8"/>
    <title>狂神说Java-ES仿京东实战</title>
    <link rel="stylesheet" th:href="@{/css/style.css}"/>
</head>

<body class="pg">
<div class="page" id="app">
    <div id="mallPage" class=" mallist tmall- page-not-market ">

        <!-- 头部搜索 -->
        <div id="header" class=" header-list-app">
            <div class="headerLayout">
                <div class="headerCon ">
                    <!-- Logo-->
                    <h1 id="mallLogo">
                        <img th:src="@{/images/jdlogo.png}" alt="">
                    </h1>

                    <div class="header-extra">

                        <!--搜索-->
                        <div id="mallSearch" class="mall-search">
                            <form name="searchTop" class="mallSearch-form clearfix">
                                <fieldset>
                                    <legend>天猫搜索</legend>
                                    <div class="mallSearch-input clearfix">
                                        <div class="s-combobox" id="s-combobox-685">
                                            <div class="s-combobox-input-wrap">
                                                <input v-model="keyword" type="text" autocomplete="off" value="dd" id="mq"
                                                       class="s-combobox-input" aria-haspopup="true">
                                            </div>
                                        </div>
                                        <button type="submit" @click.prevent="searchKey" id="searchbtn">搜索</button>
                                    </div>
                                </fieldset>
                            </form>
                            <ul class="relKeyTop">
                                <li><a>狂神说Java</a></li>
                                <li><a>狂神说前端</a></li>
                                <li><a>狂神说Linux</a></li>
                                <li><a>狂神说大数据</a></li>
                                <li><a>狂神聊理财</a></li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 商品详情页面 -->
        <div id="content">
            <div class="main">
                <!-- 品牌分类 -->
                <form class="navAttrsForm">
                    <div class="attrs j_NavAttrs" style="display:block">
                        <div class="brandAttr j_nav_brand">
                            <div class="j_Brand attr">
                                <div class="attrKey">
                                    品牌
                                </div>
                                <div class="attrValues">
                                    <ul class="av-collapse row-2">
                                        <li><a href="#"> 狂神说 </a></li>
                                        <li><a href="#"> Java </a></li>
                                    </ul>
                                </div>
                            </div>
                        </div>
                    </div>
                </form>

                <!-- 排序规则 -->
                <div class="filter clearfix">
                    <a class="fSort fSort-cur">综合<i class="f-ico-arrow-d"></i></a>
                    <a class="fSort">人气<i class="f-ico-arrow-d"></i></a>
                    <a class="fSort">新品<i class="f-ico-arrow-d"></i></a>
                    <a class="fSort">销量<i class="f-ico-arrow-d"></i></a>
                    <a class="fSort">价格<i class="f-ico-triangle-mt"></i><i class="f-ico-triangle-mb"></i></a>
                </div>

                <!-- 商品详情 -->
                <div class="view grid-nosku">

                    <div class="product" v-for="result in results">
                        <div class="product-iWrap">
                            <!--商品封面-->
                            <div class="productImg-wrap">
                                <a class="productImg">
                                    <img :src="result.img">
                                </a>
                            </div>
                            <!--价格-->
                            <p class="productPrice">
                                <em>{{result.price}}</em>
                            </p>
                            <!--标题-->
                            <p class="productTitle">
                                <a v-html="result.title"> </a>
                            </p>
                            <!-- 店铺名 -->
                            <div class="productShop">
                                <span>店铺: 狂神说Java </span>
                            </div>
                            <!-- 成交信息 -->
                            <p class="productStatus">
                                <span>月成交<em>999笔</em></span>
                                <span>评价 <a>3</a></span>
                            </p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<!--前端使用VUE,实现前后端分离-->
<script th:src="@{/js/vue.min.js}"></script>
<script th:src="@{/js/axios.min.js}"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            keyword: '',   //搜索的关键字
            results: []    //搜索的结果
        },
        methods: {
            searchKey() {
                let keyword = this.keyword;
                console.log(keyword);

                //对接后端的接口
                axios.get('search/' + keyword + "/1/10").then(res =>{
                    this.results = res.data;   //绑定数据
                })
            }
        }
    })

</script>

</body>
</html>

小结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值