当前位置:   article > 正文

ES-Springboot整合_springboot整合es

springboot整合es

目录

1.整合准备 

1.1 导入依赖

1.2 创建相关配置类

2.ES的操作 

 2.1 创建索引

2.2 删除索引 

 2.3 判断索引是否存在

 2.4 创建文档

2.5 查询文档

2.6 判断文档是否存在 

2.7 修改文档 

2.8 批量添加 

 2.9 删除文档 

2.10 复杂查询 

3.IK分词器:中文分词器

3.1 什么是IK分词器

3.2 Ik分词器的下载安装

3.3 在索引中指定ik分词器 

3.3.1 使用 ik_smart 分词算法

3.3.2 使用 ik_max_word分词算法,进行细粒度的划分: 

4.综合案例---爬取京东信息存入ES并在自己的页面展示这些数据 

4.1后端业务

4.1.1 创建springboot项目

4.1.2 添加相关依赖

4.1.3 封装爬取配置类

4.1.4 定义实体类

4.1.5创建索引

4.1.6 创建controller接口

4.1.7 service层

4.2 前端

4.2.1 前端布局 

4.2.2 main页面的配置 

4.2.3 修改router下的index.js配置 


 

1.整合准备 

1.1 导入依赖

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.78</version>
  5. </dependency>
  6. <!-- elasticsearch相关依赖-->
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-web</artifactId>
  14. </dependency>
  15. <dependency>
  16. <groupId>org.projectlombok</groupId>
  17. <artifactId>lombok</artifactId>
  18. <optional>true</optional>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-test</artifactId>
  23. <scope>test</scope>
  24. </dependency>

1.2 创建相关配置类

  1. package com.wt.config;
  2. import org.apache.http.HttpHost;
  3. import org.elasticsearch.client.RestClient;
  4. import org.elasticsearch.client.RestHighLevelClient;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. @Configuration
  8. public class ESConfig {
  9. //该对象可以对我们的ES进行相关的操作
  10. @Bean
  11. public RestHighLevelClient restHighLevelClient(){
  12. //此处的ip为本地ip,可修改为指定对象的ip
  13. RestHighLevelClient client = new RestHighLevelClient(
  14. RestClient.builder(new HttpHost("127.0.0.1",9200,"http")));
  15. return client;
  16. }
  17. }

2.ES的操作 

在测试类中导入

@Autowired
private RestHighLevelClient client;

 2.1 创建索引

  1. //创建索引----PUT /zfy-test/_doc{"mapping":{"properties"}}
  2. @Test
  3. void contextLoadss() throws Exception{
  4. //创建索引创建对象,并设置索引名
  5. CreateIndexRequest createIndexRequest = new CreateIndexRequest("zfy-test");
  6. //根据索引对象信息创建索引
  7. CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
  8. //判断索引是否创建成功---输出为true则创建成功
  9. System.out.println(createIndexResponse.isAcknowledged());
  10. }

2.2 删除索引 

  1. //删除索引-----DELETE /zfy-test
  2. @Test
  3. void deleteIndexReq() throws Exception{
  4. //创建索引删除对象,并设置索引名
  5. DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("zfy-test");
  6. //根据相关对象信息删除索引
  7. AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
  8. //查看索引是否删除成功,成功则返回true
  9. System.out.println(delete.isAcknowledged());
  10. }

 2.3 判断索引是否存在

  1. //判断索引是否存在 GET /zfy-test
  2. @Test
  3. void IndexExistsReq() throws Exception{
  4. //创建查询索引对象,并指定查询的索引
  5. GetIndexRequest indexRequest = new GetIndexRequest("zfy-test");
  6. //通过对象信息查询索引是否存在
  7. boolean exists = client.indices().exists(indexRequest, RequestOptions.DEFAULT);
  8. //返回true表示存在,否则不存在
  9. System.out.println(exists);
  10. }

 2.4 创建文档

  1. //添加文档-----PUT /zfy-test/_doc/1{name:"",age: ,"address":""}--该方法同时拥有修改功能---该id不存在则添加,存在则修改
  2. @Test
  3. void InsertDocReq() throws Exception{
  4. //创建文档信息对象---指定文档所在的索引
  5. IndexRequest indexRequest = new IndexRequest("zfy-test");
  6. //指定文档id
  7. indexRequest.id("1");
  8. //指定文档数据
  9. indexRequest.source(new User("嵇康","嵩山",23),XContentType.JSON);
  10. //根据相关信息创建文档
  11. IndexResponse index = client.index(indexRequest, RequestOptions.DEFAULT);
  12. //获取文档创建的结果---首次创建该文档则返回CREATED,若存在该文档则返回UPDATE
  13. System.out.println(index.getResult());
  14. }

2.5 查询文档

将查询出的文档封装到实体类或map中

  1. //查询文档 GET /zfy-test/_doc/1
  2. @Test
  3. void GetDocReq() throws Exception{
  4. //创建查询对象,并指定索引
  5. GetRequest getRequest = new GetRequest("zfy-test");
  6. //指定文档id
  7. getRequest.id("1");
  8. //根据相关信息查询文档是否存在
  9. GetResponse index = client.get(getRequest, RequestOptions.DEFAULT);
  10. System.out.println(index);
  11. //获取返回的数据----直接输出index也可
  12. String sourceAsString = index.getSourceAsString();
  13. //若存在该文档则返回该文档的所有数据,若不存在该文档则found为false且没有数据
  14. System.out.println(sourceAsString);
  15. //将获取到的数据封装到实体类User中
  16. User user = JSON.parseObject(sourceAsString, User.class);
  17. System.out.println(user.getAddress());
  18. //将获取的数据封装到Map中
  19. Map<String, Object> sourceAsMap = index.getSourceAsMap();
  20. System.out.println(sourceAsMap.get("name"));
  21. }

2.6 判断文档是否存在 

  1. //判断文档是否存在
  2. @Test
  3. void DocExistsReq() throws Exception{
  4. //创建查询对象,并指定索引
  5. GetRequest getRequest = new GetRequest("zfy-test");
  6. //指定文档id
  7. getRequest.id("1");
  8. //判断文档是否存在与查询文档调用方法不同,但参数相同
  9. boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
  10. //存在该文档则返回为true,反之为false
  11. System.out.println(exists);
  12. }

2.7 修改文档 

  1. //修改文档 POST /zfy-test/1/_update{"doc":{"name":""}}
  2. @Test
  3. void UpdateDocReq() throws Exception{
  4. //创建修改信息对象,并指定索引和文档id
  5. UpdateRequest updateRequest = new UpdateRequest("zfy-test","1");
  6. //创建实体类,并封装数据
  7. User user = new User();
  8. user.setName("康康");
  9. //封装要修改的值----以POST形式修改指定列
  10. updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);
  11. UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
  12. //输出修改返回的值---成功过则返回UPDATE
  13. System.out.println(update.getResult());
  14. }

2.8 批量添加 

  1. //批量添加文档
  2. @Test
  3. void bulkDoc() throws Exception{
  4. //定义容器并指定索引
  5. BulkRequest bulkRequest = new BulkRequest("zfy-test");
  6. //定义集合封装文档信息
  7. List<User> list = new ArrayList<>();
  8. list.add(new User("张三","北京",22));
  9. list.add(new User("张三他妈","天津",45));
  10. list.add(new User("李四","南京",23));
  11. list.add(new User("李四他爸","天津",47));
  12. list.add(new User("赵六","西安",22));
  13. //使用stream形式将list内的数据封装到容器中
  14. list.stream().forEach(item->{
  15. bulkRequest.add(new IndexRequest().source(JSON.toJSONString(item),XContentType.JSON));
  16. });
  17. //将封装好的信息放入该方法中进行批量添加---将会自动生成id
  18. BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
  19. //判断是否添加失败,若成功添加则返回false
  20. System.out.println(bulk.hasFailures());
  21. }

 2.9 删除文档 

  1. //删除文档
  2. @Test
  3. void deleteDocReq() throws Exception{
  4. //创建删除对象---指定索引
  5. DeleteRequest deleteRequest = new DeleteRequest("zfy-test");
  6. //指定删除id
  7. deleteRequest.id("1");
  8. //调用删除方法
  9. DeleteResponse delete = client.delete(deleteRequest, RequestOptions.DEFAULT);
  10. //获取删除返回值----成功返回为true,失败则返回false
  11. System.out.println(delete.getResult());
  12. }

批量删除 

  1. //--------批量删除
  2. @Test
  3. void deleteDocReqList() throws Exception{
  4. //创建删除对象---指定索引
  5. DeleteRequest deleteRequest = new DeleteRequest("zfy-test");
  6. //封装集合
  7. String[] arr = {"SPmjpYIBQ7K39xWU2iaZ","SfmjpYIBQ7K39xWU2iaZ","SvmjpYIBQ7K39xWU2iaZ","S_mjpYIBQ7K39xWU2iaZ","TPmjpYIBQ7K39xWU2iaZ"};
  8. Arrays.stream(arr).forEach(item->{
  9. //将要删除id封装到删除对象中
  10. deleteRequest.id(item);
  11. try{
  12. //调用删除方法
  13. DeleteResponse delete = client.delete(deleteRequest, RequestOptions.DEFAULT);
  14. //获取删除返回值----成功返回为true,失败则返回false
  15. System.out.println(delete.getResult());
  16. }catch (Exception e){
  17. e.printStackTrace();
  18. }
  19. });
  20. }

2.10 复杂查询 

  1. //搜索查询---GET /索引/_search
  2. // {
  3. // "query":{
  4. // "":{}
  5. // },
  6. // "from":
  7. // "size":
  8. // "_source":["",""],
  9. // "sort":{}
  10. // }
  11. //1. 搜索请求对象SearchRequest
  12. //2. 构建一个条件对象SearchSourceBuilder
  13. //3. 把条件对象放入搜索请求对象中
  14. //4. 执行搜索功能
  15. //复杂查询
  16. @Test
  17. void testSearchReq() throws Exception{
  18. //创建复杂查询对象---------
  19. SearchRequest searchRequest = new SearchRequest("zfy-test");
  20. //创建一个条件对象用来封装各种条件
  21. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  22. //创建一个对象来封装查询条件query
  23. MatchQueryBuilder queryBuilder = new MatchQueryBuilder("name","李");
  24. //使用条件对象来封装查询条件---条件
  25. sourceBuilder.query(queryBuilder);
  26. //指定查询的列------条件
  27. String[] arr = {"name","address","age"};
  28. String[] att = {};
  29. sourceBuilder.fetchSource(arr,att); //指定查询列和不查询列
  30. //分页查询---条件
  31. sourceBuilder.from(0);
  32. sourceBuilder.size(5);
  33. //排序----条件
  34. // SortOrder sortOrder = SortOrder.ASC;------定义排序方式
  35. sourceBuilder.sort("age",SortOrder.DESC);
  36. //创建一个高亮对象,封装高亮条件
  37. HighlightBuilder highlightBuilder = new HighlightBuilder();
  38. //指定高亮列----也可以用fields,全局定义高亮
  39. highlightBuilder.field("name");
  40. highlightBuilder.preTags("<font color='red'>");
  41. highlightBuilder.postTags("</font>");
  42. sourceBuilder.highlighter(highlightBuilder);
  43. //将封装好的条件对象给searchRequest
  44. searchRequest.source(sourceBuilder);
  45. //将封装好所有条件的对象给查询方法
  46. SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
  47. //输出根据条件查出的总条数
  48. System.out.println("命中条数/查询总数:"+search.getHits().getTotalHits().value);
  49. //将查出的数据封住为一个数组
  50. SearchHit[] hits = search.getHits().getHits();
  51. //遍历数组
  52. Arrays.stream(hits).forEach(item->{
  53. //输出遍历对象
  54. System.out.println(item.getSourceAsString());
  55. });
  56. Arrays.stream(hits).forEach(item->{
  57. //遍历输出高亮的字段
  58. System.out.println(item.getHighlightFields());
  59. });
  60. }

3.IK分词器:中文分词器

3.1 什么是IK分词器

ElasticSearch 几种常用分词器如下:


分词∶即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如“我爱中国"会被分为"我""爱""中""国”,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。

IK提供了两个分词算法:ik_smart和ik_max_word,其中ik smart为最少切分,ik_max_word为最细粒度划分!

ik_max_word: 会将文本做最细粒度的拆分,比如会将"中华人民共和国国歌"拆分为"中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌",会穷尽各种可能的组合;

ik_smart: 会做最粗粒度的拆分,比如会将"中华人民共和国国歌"拆分为"中华人民共和国,国歌"。

3.2 Ik分词器的下载安装

下载地址:GitHub - medcl/elasticsearch-analysis-ik: The IK Analysis plugin integrates Lucene IK analyzer into elasticsearch, support customized dictionary.
注意:IK分词器插件的版本要和ElasticSearch的版本一致

3.3 在索引中指定ik分词器 

我们用分词器对 “万里顾一程” 进行分词:

3.3.1 使用 ik_smart 分词算法

3.3.2 使用 ik_max_word分词算法,进行细粒度的划分: 

  1. GET _analyze
  2. {
  3. "analyzer": "ik_max_word",
  4. "text": "万里顾一程"
  5. }

分词结果:

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "万里",
  5. "start_offset" : 0,
  6. "end_offset" : 2,
  7. "type" : "CN_WORD",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "万",
  12. "start_offset" : 0,
  13. "end_offset" : 1,
  14. "type" : "TYPE_CNUM",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "里",
  19. "start_offset" : 1,
  20. "end_offset" : 2,
  21. "type" : "COUNT",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "顾",
  26. "start_offset" : 2,
  27. "end_offset" : 3,
  28. "type" : "CN_CHAR",
  29. "position" : 3
  30. },
  31. {
  32. "token" : "一程",
  33. "start_offset" : 3,
  34. "end_offset" : 5,
  35. "type" : "CN_WORD",
  36. "position" : 4
  37. },
  38. {
  39. "token" : "一",
  40. "start_offset" : 3,
  41. "end_offset" : 4,
  42. "type" : "TYPE_CNUM",
  43. "position" : 5
  44. },
  45. {
  46. "token" : "程",
  47. "start_offset" : 4,
  48. "end_offset" : 5,
  49. "type" : "CN_CHAR",
  50. "position" : 6
  51. }
  52. ]
  53. }

使用上面两种分词算法后,发现 “万里顾一程”被分成了“万里”、“顾”、“一程”,这是因为在IK自带的字典中没有“顾一程”这个词,如果想得到“顾一程”这个词,怎么办呢?

此时就需要配置自定义字典--即自定义词组群,就是在IK分词器字典中加入我们自定义的字典,在词典中加入想要的词。

在ik分词器文件的config目录中新建自定义的字典文件,以.dic为后缀,并在文件中加入“顾一程”:

IK控制器自定义词典的详细步骤:

4.综合案例---爬取京东信息存入ES并在自己的页面展示这些数据 

4.1后端业务

4.1.1 创建springboot项目

4.1.2 添加相关依赖

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.78</version>
  5. </dependency>
  6. <!-- 爬虫java包-->
  7. <dependency>
  8. <groupId>org.jsoup</groupId>
  9. <artifactId>jsoup</artifactId>
  10. <version>1.11.3</version>
  11. </dependency>

4.1.3 封装爬取配置类

  1. package com.wt.utils;
  2. import com.wt.entity.Product;
  3. import org.jsoup.Jsoup;
  4. import org.jsoup.nodes.Document;
  5. import org.jsoup.nodes.Element;
  6. import org.jsoup.select.Elements;
  7. import java.net.URL;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /**
  11. * @Author wt
  12. * @Date 2022/8/17 10:40
  13. * @PackageName:com.wt.utils
  14. * @ClassName: HtmlParses
  15. * @Description: TODO
  16. * @Version 1.0
  17. */
  18. public class HtmlParsesUtil {
  19. //从京东爬虫----有可能从数据库中。
  20. public static List<Product> parseJd(String keyword) throws Exception {
  21. String path="https://search.jd.com/Search?keyword="+keyword;
  22. //Document整个网页对象
  23. Document document = Jsoup.parse(new URL(path), 30000);
  24. Element j_goodsList = document.getElementById("J_goodsList");
  25. Elements li = j_goodsList.getElementsByTag("li");
  26. List<Product> list=new ArrayList<>();
  27. for (Element element:li){
  28. //爬取商品价格
  29. String pprice = element.getElementsByClass("p-price").eq(0).text();
  30. //爬取商品信息
  31. String pname = element.getElementsByClass("p-name").eq(0).text();
  32. //爬取商品图片地址
  33. String img = element.getElementsByTag("img").eq(0).attr("data-lazy-img");
  34. list.add(new Product(pname,pprice,img));
  35. }
  36. return list;
  37. }
  38. }

4.1.4 定义实体类

  1. package com.wt.entity;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. /**
  6. * @Author wt
  7. * @Date 2022/8/16 17:03
  8. * @PackageName:com.wt.entity
  9. * @ClassName: Product
  10. * @Description: TODO
  11. * @Version 1.0
  12. */
  13. @Data
  14. @AllArgsConstructor
  15. @NoArgsConstructor
  16. public class Product {
  17. private String title;
  18. private String price;
  19. private String imgUrl;
  20. }

4.1.5创建索引

  1. PUT /jd-test
  2. {
  3. "mappings": {
  4. "properties": {
  5. "title":{
  6. "type": "text",
  7. "analyzer": "ik_max_word"
  8. },
  9. "price":{
  10. "type": "keyword"
  11. },
  12. "imgUrl":{
  13. "type": "keyword"
  14. }
  15. }
  16. },
  17. "settings": {
  18. "index.analysis.analyzer.default.type":"ik_max_word"
  19. }
  20. }

4.1.6 创建controller接口

  1. package com.wt.controller;
  2. import com.wt.service.ProductService;
  3. import com.wt.vo.CommonResult;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.*;
  6. /**
  7. * @Author wt
  8. * @Date 2022/8/17 10:43
  9. * @PackageName:com.wt.controller
  10. * @ClassName: ProductController
  11. * @Description: TODO
  12. * @Version 1.0
  13. */
  14. @RestController
  15. @RequestMapping("/product")
  16. @CrossOrigin
  17. public class ProductController {
  18. @Autowired
  19. private ProductService productService;
  20. //爬取数据并添加进es
  21. @GetMapping("/export/{keyword}")
  22. public CommonResult export(@PathVariable String keyword) throws Exception{
  23. System.out.println("==========="+keyword);
  24. CommonResult result = productService.export(keyword);
  25. return result;
  26. }
  27. @GetMapping("search/{currentPage}/{pageSize}/{keyword}")
  28. public CommonResult search(@PathVariable String keyword,@PathVariable Integer currentPage, @PathVariable Integer pageSize ) throws Exception{
  29. CommonResult result = productService.search(keyword,currentPage,pageSize);
  30. System.out.println(result);
  31. return result;
  32. }
  33. }

4.1.7 service层

  1. package com.wt.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.wt.entity.Product;
  4. import com.wt.utils.HtmlParsesUtil;
  5. import com.wt.vo.CommonResult;
  6. import org.apache.lucene.search.TotalHits;
  7. import org.elasticsearch.action.bulk.BulkRequest;
  8. import org.elasticsearch.action.bulk.BulkResponse;
  9. import org.elasticsearch.action.index.IndexRequest;
  10. import org.elasticsearch.action.search.SearchRequest;
  11. import org.elasticsearch.action.search.SearchResponse;
  12. import org.elasticsearch.client.RequestOptions;
  13. import org.elasticsearch.client.RestHighLevelClient;
  14. import org.elasticsearch.common.text.Text;
  15. import org.elasticsearch.common.xcontent.XContentType;
  16. import org.elasticsearch.index.query.MatchQueryBuilder;
  17. import org.elasticsearch.index.query.QueryBuilder;
  18. import org.elasticsearch.index.query.QueryBuilders;
  19. import org.elasticsearch.index.query.TermQueryBuilder;
  20. import org.elasticsearch.search.SearchHit;
  21. import org.elasticsearch.search.SearchHits;
  22. import org.elasticsearch.search.builder.SearchSourceBuilder;
  23. import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
  24. import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
  25. import org.springframework.beans.factory.annotation.Autowired;
  26. import org.springframework.stereotype.Service;
  27. import java.util.*;
  28. /**
  29. * @Author wt
  30. * @Date 2022/8/17 10:44
  31. * @PackageName:com.wt.service
  32. * @ClassName: ProductService
  33. * @Description: TODO
  34. * @Version 1.0
  35. */
  36. @Service
  37. public class ProductService {
  38. @Autowired
  39. private RestHighLevelClient client;
  40. //爬取数据并添加进es
  41. public CommonResult export(String keyword) throws Exception {
  42. //将爬取到的数据存储到集合中
  43. List<Product> list = HtmlParsesUtil.parseJd(keyword);
  44. System.out.println(list);
  45. BulkRequest bulkRequest = new BulkRequest("jd-test");
  46. // list.stream().forEach(item->{
  47. // IndexRequest request = new IndexRequest();
  48. // request.source(JSON.toJSONString(item), XContentType.JSON);
  49. // bulkRequest.add(request);
  50. // });
  51. for (Product product:list){
  52. IndexRequest indexRequest=new IndexRequest();
  53. indexRequest.source(JSON.toJSONString(product), XContentType.JSON);
  54. bulkRequest.add(indexRequest);
  55. }
  56. System.out.println(JSON.toJSONString(bulkRequest));
  57. //批量添加文档
  58. BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
  59. // BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
  60. System.out.println(bulk);
  61. if (bulk.hasFailures()){
  62. return new CommonResult(5000,"添加失败",null);
  63. }
  64. return new CommonResult(2000,"添加成功",bulk);
  65. }
  66. public CommonResult search(String keyword, Integer currentPage, Integer pageSize) throws Exception{
  67. SearchRequest searchRequest = new SearchRequest("jd-test");
  68. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  69. //传入查询内容
  70. TermQueryBuilder title = QueryBuilders.termQuery("title", keyword);
  71. sourceBuilder.query(title);
  72. sourceBuilder.from((currentPage-1)*pageSize);
  73. sourceBuilder.size(pageSize);
  74. HighlightBuilder highlightBuilder = new HighlightBuilder();
  75. highlightBuilder.field("title");
  76. highlightBuilder.preTags("<font color='red'>");
  77. highlightBuilder.postTags("</font>");
  78. sourceBuilder.highlighter(highlightBuilder);
  79. searchRequest.source(sourceBuilder);
  80. SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
  81. //System.out.println(search);
  82. SearchHit[] hits = search.getHits().getHits();
  83. List<Map<String,Object>> list = new ArrayList<>();
  84. long totalHits = search.getHits().getTotalHits().value;
  85. //总条数total
  86. System.out.println(totalHits);
  87. Arrays.stream(hits).forEach(item->{
  88. Map<String, Object> sourceAsMap = item.getSourceAsMap();
  89. Map<String, HighlightField> highlightFields = item.getHighlightFields();
  90. HighlightField title1 = highlightFields.get("title");
  91. Text[] fragments = title1.getFragments();
  92. StringBuilder stringBuilder = new StringBuilder();
  93. for (Text text:fragments){
  94. stringBuilder.append(text);
  95. }
  96. sourceAsMap.put("title",stringBuilder);
  97. list.add(sourceAsMap);
  98. });
  99. //将查出来的数据和总条数存储在map中
  100. Map map = new HashMap();
  101. map.put("list",list);
  102. map.put("total",totalHits);
  103. return new CommonResult(2000,"查询成功",map);
  104. }
  105. }

4.2 前端

4.2.1 前端布局 

  1. <template>
  2. <div class="page">
  3. <div id="app" class=" mallist tmall- page-not-market ">
  4. <!-- 头部搜索 -->
  5. <div id="header" class=" header-list-app">
  6. <div class="headerLayout">
  7. <div class="headerCon ">
  8. <!-- Logo-->
  9. <h1 id="mallLogo">
  10. <img src="../assets/jdlogo.png" alt="">
  11. </h1>
  12. <div class="header-extra">
  13. <!--搜索-->
  14. <div id="mallSearch" class="mall-search">
  15. <form name="searchTop" class="mallSearch-form clearfix">
  16. <fieldset>
  17. <legend>天猫搜索</legend>
  18. <div class="mallSearch-input clearfix">
  19. <div class="s-combobox" id="s-combobox-685">
  20. <div class="s-combobox-input-wrap">
  21. <input v-model="keyword" type="text" autocomplete="off" id="mq"
  22. class="s-combobox-input" aria-haspopup="true">
  23. </div>
  24. </div>
  25. <button type="submit" @click.prevent="searchKey" id="searchbtn">搜索</button>
  26. </div>
  27. </fieldset>
  28. </form>
  29. <ul class="relKeyTop">
  30. <li><a>老王说Java</a></li>
  31. <li><a>老王说前端</a></li>
  32. <li><a>老王说Linux</a></li>
  33. <li><a>老王说大数据</a></li>
  34. <li><a>老王聊理财</a></li>
  35. </ul>
  36. </div>
  37. </div>
  38. </div>
  39. </div>
  40. </div>
  41. <!-- 商品详情页面 -->
  42. <div id="content">
  43. <div class="main">
  44. <!-- 品牌分类 -->
  45. <form class="navAttrsForm">
  46. <div class="attrs j_NavAttrs" style="display:block">
  47. <div class="brandAttr j_nav_brand">
  48. <div class="j_Brand attr">
  49. <div class="attrKey">
  50. 品牌
  51. </div>
  52. <div class="attrValues">
  53. <ul class="av-collapse row-2">
  54. <li><a href="#"> 老王说 </a></li>
  55. <li><a href="#"> Java </a></li>
  56. </ul>
  57. </div>
  58. </div>
  59. </div>
  60. </div>
  61. </form>
  62. <!-- 排序规则 -->
  63. <div class="filter clearfix">
  64. <a class="fSort fSort-cur">综合<i class="f-ico-arrow-d"></i></a>
  65. <a class="fSort">人气<i class="f-ico-arrow-d"></i></a>
  66. <a class="fSort">新品<i class="f-ico-arrow-d"></i></a>
  67. <a class="fSort">销量<i class="f-ico-arrow-d"></i></a>
  68. <a class="fSort">价格<i class="f-ico-triangle-mt"></i><i class="f-ico-triangle-mb"></i></a>
  69. </div>
  70. <!-- 商品详情 -->
  71. <div class="view grid-nosku" >
  72. <div class="product" v-for="item in results">
  73. <div class="product-iWrap">
  74. <!--商品封面-->
  75. <div class="productImg-wrap">
  76. <a class="productImg">
  77. <img :src="item.imgUrl">
  78. </a>
  79. </div>
  80. <!--价格-->
  81. <p class="productPrice">
  82. <em>{{item.price}}</em>
  83. </p>
  84. <!--标题-->
  85. <p class="productTitle">
  86. <a v-html="item.title"> </a>
  87. </p>
  88. <!-- 店铺名 -->
  89. <div class="productShop">
  90. <span>店铺: 老王说Java </span>
  91. </div>
  92. <!-- 成交信息 -->
  93. <p class="productStatus">
  94. <span>月成交<em>999</em></span>
  95. <span>评价 <a>3</a></span>
  96. </p>
  97. </div>
  98. </div>
  99. </div>
  100. </div>f
  101. </div>
  102. </div>
  103. <el-pagination
  104. @size-change="handleSizeChange"
  105. @current-change="handleCurrentChange"
  106. :current-page="currentPage"
  107. :page-sizes="pageSizes"
  108. :page-size="pageSize"
  109. layout="total, sizes, prev, pager, next, jumper"
  110. :total="total">
  111. </el-pagination>
  112. </div>
  113. </template>
  114. <script>
  115. export default {
  116. name: "jd",
  117. data(){
  118. return {
  119. keyword: '', // 搜索的关键字
  120. results:[], // 后端返回的结果
  121. //当前页码
  122. currentPage: 1,
  123. pageSizes: [20, 30, 40, 60],
  124. pageSize: 20,
  125. total: 0,
  126. }
  127. },
  128. methods:{
  129. searchKey(){
  130. var keyword = this.keyword;
  131. this.$http.get('http://192.168.22.1:8080/product/search/'+this.currentPage+"/"+this.pageSize+"/"+keyword).then(response=>{
  132. console.log(response.data.data);
  133. this.total = response.data.data.total;
  134. this.results=response.data.data.list;
  135. })
  136. },
  137. //分页操作
  138. handleSizeChange(val) {
  139. console.log("每页"+ val+"条");
  140. this.pageSize = val;
  141. this.searchKey();
  142. },
  143. handleCurrentChange(val) {
  144. console.log("当前页:"+val);
  145. this.currentPage = val;
  146. this.searchKey();
  147. }
  148. }
  149. }
  150. </script>
  151. <style>
  152. /*** uncss> filename: http://localhost:9090/css/global.css ***/body,button,fieldset,form,h1,input,legend,li,p,ul{margin:0;padding:0}body,button,input{font:12px/1.5 tahoma,arial,"\5b8b\4f53";-ms-overflow-style:scrollbar}button,h1,input{font-size:100%}em{font-style:normal}ul{list-style:none}a{text-decoration:none}a:hover{text-decoration:underline}legend{color:#000}fieldset,img{border:0}#content,#header{margin-left:auto;margin-right:auto}html{zoom:expression(function(ele){ ele.style.zoom = "1"; document.execCommand("BackgroundImageCache", false, true); }(this))}@font-face{font-family:mui-global-iconfont;src:url(//at.alicdn.com/t/font_1401963178_8135476.eot);src:url(//at.alicdn.com/t/font_1401963178_8135476.eot?#iefix) format('embedded-opentype'),url(//at.alicdn.com/t/font_1401963178_8135476.woff) format('woff'),url(//at.alicdn.com/t/font_1401963178_8135476.ttf) format('truetype'),url(//at.alicdn.com/t/font_1401963178_8135476.svg#iconfont) format('svg')}#mallPage{width:auto;min-width:990px;background-color:transparent}#content{width:990px;margin:auto}#mallLogo{float:left;z-index:9;padding-top:28px;width:280px;height:64px;line-height:64px;position:relative}.page-not-market #mallLogo{width:400px}.clearfix:after,.clearfix:before,.headerCon:after,.headerCon:before{display:table;content:"";overflow:hidden}#mallSearch legend{display:none}.clearfix:after,.headerCon:after{clear:both}.clearfix,.headerCon{zoom:1}#mallPage #header{margin-top:-30px;width:auto;margin-bottom:0;min-width:990px;background:#fff}#header{height:122px;margin-top:-26px!important;background:#fff;min-width:990px;width:auto!important;position:relative;z-index:1000}#mallSearch #mq,#mallSearch fieldset,.mallSearch-input{position:relative}.headerLayout{width:990px;padding-top:26px;margin:0 auto}.header-extra{overflow:hidden}#mallSearch{float:right;padding-top:25px;width:390px;overflow:hidden}.mallSearch-form{border:solid #FF0036;border-width:3px 0 3px 3px}.mallSearch-input{background:#fff;height:30px}#mallSearch #mq{color:#000;margin:0;z-index:2;width:289px;height:20px;line-height:20px;padding:5px 3px 5px 5px;outline:0;border:none;font-weight:900;background:url(data:image/gif;base64,R0lGODlhAQADAJEAAObm5t3d3ff39wAAACH5BAAAAAAALAAAAAABAAMAAAICDFQAOw==) repeat-x;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}#mallSearch button{position:absolute;right:0;top:0;width:90px;border:0;font-size:16px;letter-spacing:4px;cursor:pointer;color:#fff;background-color:#FF0036;height:30px;overflow:hidden;font-family:'\5FAE\8F6F\96C5\9ED1',arial,"\5b8b\4f53"}#mallSearch .s-combobox{height:30px}#mallSearch .s-combobox .s-combobox-input:focus{outline:0}button::-moz-focus-inner{border:0;padding:0;margin:0}.page-not-market #mallSearch{width:540px!important}.page-not-market #mq{width:439px!important}
  153. /*** uncss> filename: http://localhost:9090/css/test.css ***/#mallSearch{float:none}.page-not-market #mallLogo{width:280px}.header-list-app #mallSearch{width:448px!important}.header-list-app #mq{width:347px!important}@media (min-width:1210px){#header .headerCon,#header .headerLayout,.main{width:1190px!important}.header-list-app #mallSearch{width:597px!important}.header-list-app #mq{width:496px!important}}@media (min-width:600px) and (max-width:800px) and (orientation:portrait){.pg .page{min-width:inherit!important}.pg #mallPage,.pg #mallPage #header{min-width:740px!important}.pg #header .headerCon,.pg #header .headerLayout,.pg .main{width:740px!important}.pg #mallPage #mallLogo{width:260px}.pg #header{min-width:inherit}.pg #mallSearch .mallSearch-input{padding-right:95px}.pg #mallSearch .s-combobox{width:100%!important}.pg #mallPage .header-list-app #mallSearch{width:auto!important}.pg #mallPage .header-list-app #mallSearch #mq{width:100%!important;padding:5px 0 5px 5px}}i{font-style:normal}.main,.page{position:relative}.page{overflow:hidden}@font-face{font-family:tm-list-font;src:url(//at.alicdn.com/t/font_1442456441_338337.eot);src:url(//at.alicdn.com/t/font_1442456441_338337.eot?#iefix) format('embedded-opentype'),url(//at.alicdn.com/t/font_1442456441_338337.woff) format('woff'),url(//at.alicdn.com/t/font_1442456441_338337.ttf) format('truetype'),url(//at.alicdn.com/t/font_1442456441_338337.svg#iconfont) format('svg')}::selection{background:rgba(0,0,0,.1)}*{-webkit-tap-highlight-color:rgba(0,0,0,.3)}b{font-weight:400}.page{background:#fff;min-width:990px}#content{margin:0!important;width:100%!important}.main{margin:auto;width:990px}.main img{-ms-interpolation-mode:bicubic}.fSort i{background:url(//img.alicdn.com/tfs/TB1XClLeAY2gK0jSZFgXXc5OFXa-165-206.png) 9999px 9999px no-repeat}#mallSearch .s-combobox{width:auto}::-ms-clear,::-ms-reveal{display:none}.attrKey{white-space:nowrap;text-overflow:ellipsis}.attrs{border-top:1px solid #E6E2E1}.attrs a{outline:0}.attr{background-color:#F7F5F5;border-color:#E6E2E1 #E6E2E1 #D1CCC7;border-style:solid solid dotted;border-width:0 1px 1px}.attr ul:after,.attr:after{display:block;clear:both;height:0;content:' '}.attrKey{float:left;padding:7px 0 0;width:10%;color:#B0A59F;text-indent:13px}.attrKey{display:block;height:16px;line-height:16px;overflow:hidden}.attrValues{position:relative;float:left;background-color:#FFF;width:90%;padding:4px 0 0;overflow:hidden}.attrValues ul{position:relative;margin-right:105px;margin-left:25px}.attrValues ul.av-collapse{overflow:hidden}.attrValues li{float:left;height:22px;line-height:22px}.attrValues li a{position:relative;color:#806F66;display:inline-block;padding:1px 20px 1px 4px;line-height:20px;height:20px;white-space:nowrap}.attrValues li a:hover{color:#ff0036;text-decoration:none}.brandAttr .attr{border:2px solid #D1CCC7;margin-top:-1px}.brandAttr .attrKey{padding-top:9px}.brandAttr .attrValues{padding-top:6px}.brandAttr .av-collapse{overflow:hidden;max-height:60px}.brandAttr li{margin:0 8px 8px 0}.brandAttr li a{text-overflow:ellipsis;overflow:hidden}.navAttrsForm{position:relative}.relKeyTop{padding:4px 0 0;margin-left:-13px;height:16px;overflow:hidden;width:100%}.relKeyTop li{display:inline-block;border-left:1px solid #ccc;line-height:1.1;padding:0 12px}.relKeyTop li a{color:#999}.relKeyTop li a:hover{color:#ff0036;text-decoration:none}.filter i{display:inline-block;overflow:hidden}.filter{margin:10px 0;padding:5px;position:relative;z-index:10;background:#faf9f9;color:#806f66}.filter i{position:absolute}.filter a{color:#806f66;cursor:pointer}.filter a:hover{color:#ff0036;text-decoration:none}.fSort{float:left;height:22px;line-height:20px;line-height:24px\9;border:1px solid #ccc;background-color:#fff;z-index:10}.fSort{position:relative}.fSort{display:inline-block;margin-left:-1px;overflow:hidden;padding:0 15px 0 5px}.fSort:hover,a.fSort-cur{color:#ff0036;background:#F1EDEC}.fSort i{top:6px;right:5px;width:7px;height:10px;line-height:10px}.fSort .f-ico-arrow-d{background-position:-22px -23px}.fSort-cur .f-ico-arrow-d,.fSort:hover .f-ico-arrow-d{background-position:-30px -23px}i.f-ico-triangle-mb,i.f-ico-triangle-mt{border:4px solid transparent;height:0;width:0}i.f-ico-triangle-mt{border-bottom:4px solid #806F66;top:2px}i.f-ico-triangle-mb{border-top:4px solid #806F66;border-width:3px\9;right:6px\9;top:12px}:root i.f-ico-triangle-mb{border-width:4px\9;right:5px\9}i.f-ico-triangle-mb,i.f-ico-triangle-mt{border:4px solid transparent;height:0;width:0}i.f-ico-triangle-mt{border-bottom:4px solid #806F66;top:2px}i.f-ico-triangle-mb{border-top:4px solid #806F66;border-width:3px\9;right:6px\9;top:12px}:root i.f-ico-triangle-mb{border-width:4px\9;right:5px\9}.view:after{clear:both;content:' '}.productImg,.productPrice em b{vertical-align:middle}.product{position:relative;float:left;padding:0;margin:0 0 20px;line-height:1.5;overflow:visible;z-index:1}.product:hover{overflow:visible;z-index:3;background:#fff}.product-iWrap{position:absolute;background-color:#fff;margin:0;padding:4px 4px 0;font-size:0;border:1px solid #f5f5f5;border-radius:3px}.product-iWrap *{font-size:12px}.product:hover .product-iWrap{height:auto;margin:-3px;border:4px solid #ff0036;border-radius:0;-webkit-transition:border-color .2s ease-in;-moz-transition:border-color .2s ease-in;-ms-transition:border-color .2s ease-in;-o-transition:border-color .2s ease-in;transition:border-color .2s ease-in}.productPrice,.productShop,.productStatus,.productTitle{display:block;overflow:hidden;margin-bottom:3px}.view:after{display:block}.view{margin-top:10px}.view:after{height:0}.productImg-wrap{display:table;table-layout:fixed;height:210px;width:100%;padding:0;margin:0 0 5px}.productImg-wrap a,.productImg-wrap img{max-width:100%;max-height:210px}.productImg{display:table-cell;width:100%;text-align:center}.productImg img{display:block;margin:0 auto}.productPrice{font-family:arial,verdana,sans-serif!important;color:#ff0036;font-size:14px;height:30px;line-height:30px;margin:0 0 5px;letter-spacing:normal;overflow:inherit!important;white-space:nowrap}.productPrice *{height:30px}.productPrice em{float:left;font-family:arial;font-weight:400;font-size:20px;color:#ff0036}.productPrice em b{margin-right:2px;font-weight:700;font-size:14px}.productTitle{display:block;color:#666;height:14px;line-height:12px;margin-bottom:3px;word-break:break-all;font-size:0;position:relative}.productTitle *{font-size:12px;font-family:\5FAE\8F6F\96C5\9ED1;line-height:14px}.productTitle a{color:#333}.productTitle a:hover{color:#ff0036!important}.productTitle a:visited{color:#551A8B!important}.product:hover .productTitle{height:14px}.productShop{position:relative;height:22px;line-height:20px;margin-bottom:5px;color:#999;white-space:nowrap;overflow:visible}.productStatus{position:relative;height:32px;border:none;border-top:1px solid #eee;margin-bottom:0;color:#999}.productStatus span{float:left;display:inline-block;border-right:1px solid #eee;width:39%;padding:10px 1px;margin-right:6px;line-height:12px;text-align:left;white-space:nowrap}.productStatus a,.productStatus em{margin-top:-8px;font-family:arial;font-size:12px;font-weight:700}.productStatus em{color:#b57c5b}.productStatus a{color:#38b}.productImg-wrap{position:relative}.product-iWrap{min-height:98%;width:210px}.view{padding-left:5px;padding-right:5px}.view{width:1023px}.view .product{width:220px;margin-right:33px}@media (min-width:1210px){.view{width:1210px;padding-left:5px;padding-right:5px}.view .product{width:220px;margin-right:20px}}@media (min-width:600px) and (max-width:800px) and (orientation:portrait){.view{width:775px;padding-left:5px;padding-right:5px}.view .product{width:220px;margin-right:35px}}.product{height:372px}.grid-nosku .product{height:333px}
  154. </style>

4.2.2 main页面的配置 

4.2.3 修改router下的index.js配置 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/566572
推荐阅读
相关标签
  

闽ICP备14008679号