首页 > 其他分享 >ElasticSearch 8.x 实战

ElasticSearch 8.x 实战

时间:2023-05-15 14:24:32浏览次数:48  
标签:实战 String keyword title List ElasticSearch new public

ElasticSearch 8.x 实战

Github 地址ElasticSearch 仿京东搜索项目实现

爬虫

爬取数据:获取请求返回的页面信息,筛选出我们想要的数据就可以了,直接使用 jsoup

  1. pom.xml 导入依赖
<!--解析网页-->
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.16.1</version>
</dependency>
  1. 新建 pojo 文件夹,新建 Java 类 Content
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
    private String title;
    private String img;
    private String price;
}
  1. 新建 utils 文件夹,新建 Java 类 HtmlParseUtil
@Component
public class HtmlParseUtil {
    public static void main(String[] args) throws Exception {
        new HtmlParseUtil().parseJD("java").forEach(System.out::println);
    }

    public List<Content> parseJD(String keyword) throws Exception {
        // 获取请求 https://search.jd.com/Search?keyword=java
        // 前提,需要联网,ajax 不能获取到
        String url = "https://search.jd.com/Search?keyword=" + keyword;
        // 解析网页(Jsoup 返回的 Document 就是浏览器 Document 对象)
        Document document = Jsoup.parse(new URL(url), 30000);
        // 所有在 js 中可以使用的方法,这里都能用
        Element element = document.getElementById("J_goodsList");
        // System.out.println(element.html());
        // 获取所有的 li 元素
        ArrayList<Content> goodsList = new ArrayList<>();
        if (element != null) {
            Elements elements = element.getElementsByTag("li");
            // 获取元素中的内容,这里的 el 就是每一个 li 标签了
            for (Element el : elements) {
                // 关于这种图片特别多的网站,所有的图片都是延迟加载的
                // data-lazy-img
                if (el.attr ("class").equalsIgnoreCase ("gl-item")) {
                    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();
                    goodsList.add(new Content(title, img, price));
                }
            }
        }
        return goodsList;
    }
}
  1. 新建 service 文件夹,新建 Java 类 ContentService
// 业务编写
@Service
public class ContentService {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    // 1. 解析数据放入 es 索引
    public Boolean parseContent(String keywords) throws Exception {
        List<Content> contents = new HtmlParseUtil().parseJD(keywords);
        // 把查询的数据放入 es 中
        List<BulkOperation> bulkOperationArrayList = new ArrayList<>();
        // 遍历添加到 bulk 中
        // 如果不写 id 的话,就是随机 id
        for (Content content : contents) {
            bulkOperationArrayList.add(BulkOperation.of(o -> o.index(i -> i.document(content))));
        }

        BulkResponse bulkResponse = elasticsearchClient.bulk(b -> b.index("jd_goods")
                .operations(bulkOperationArrayList));
        return !bulkResponse.errors();

    }

    // 2. 获取这些数据
    public List<Map<String, Object>> searchPage(String keyword, int pageNo, int pageSize) {
        try {
            if (pageNo <= 0) {
                pageNo = 1;
            }
            if (pageSize <= 0) {
                pageSize = 10;
            }
            // 条件搜索
            int finalPageNo = pageNo;
            int finalPageSize = pageSize;
            SearchResponse<Content> searchResponse = elasticsearchClient.search(s -> s
                    .index("jd_goods")
                    //查询 title 字段包含关键字的 document (不使用分词器精确查找)
                    .query(q -> q
                            .term(t -> t
                                    .field("title")
                                    .value(v -> v.stringValue(keyword))
                            ))
                    //分页查询,从第 PageNo 页开始查询 PageSize 个 document
                    .from(finalPageNo)
                    .size(finalPageSize), Content.class
            );
            // 解析结果
            List<Map<String, Object>> list = new ArrayList<>();
            ObjectMapper objectMapper = new ObjectMapper();
            for (Hit<Content> hit : searchResponse.hits().hits()) {
                Content content = hit.source();
                Map<String, Object> map = objectMapper.convertValue(content, new TypeReference<Map<String, Object>>() {
                });
                list.add(map);
            }
            return list;


        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

}
  1. 新建 controller 文件夹,新建 Java 类 ContentController
@RestController
public class ContentController {

    @Autowired
    private ContentService contentService;

    @GetMapping("/parse/{keywords}")
    public Boolean parse(@PathVariable("keywords") String keywords) throws Exception {
        return contentService.parseContent(keywords);
    }

    @GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
    public List<Map<String, Object>> search(@PathVariable("keyword") String keyword,
                                            @PathVariable("pageNo") int pageNo,
                                            @PathVariable("pageSize") int pageSize) throws Exception {
        return contentService.searchPage(keyword, pageNo, pageSize);
    }
}
  1. 测试:在浏览器中输入 http://localhost:9090/search/java/1/10 查看数据

前后端分离

使用 Vue 实现前后端分离,具体实现步骤如下:

  1. 新建文件夹,注意名字不要出现中文,进入 cmd 下载 vueaxios
npm install vue
npm install axios
  1. axios.min.jsvue.min.js 放入 resources/static/js

  2. index.html 使用 Vue

<!--前端使用 Vue 实现前后端分离-->
<script th:src="@{/js/axios.min.js}"></script>
<script th:src="@{/js/vue.min.js}"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            keyword: '', // 搜索的关键字
            results: []  // 搜索的结果
        },
        methods: {
            searchKey() {
                let keyword = this.keyword;
                // 对接后端接口
                axios.get("search/" + keyword + "/1/10").then(response => {
                    this.results = response.data; // 绑定数据
                })
            }
        }
    })
</script>

搜索高亮

  1. 修改 service/ContentService
// 2. 获取这些数据
public List<Map<String, Object>> searchPage(String keyword, int pageNo, int pageSize) {
    try {
        if (pageNo <= 0) {
            pageNo = 1;
        }
        if (pageSize <= 0) {
            pageSize = 10;
        }
        // 条件搜索
        int finalPageNo = pageNo;
        int finalPageSize = pageSize;
        SearchResponse<Content> searchResponse = elasticsearchClient.search(s -> s
                .index("jd_goods")
                // 查询 title 字段包含关键字的 document (不使用分词器精确查找)
                .query(q -> q
                        .term(t -> t
                                .field("title")
                                .value(v -> v.stringValue(keyword))
                        ))
                // 高亮 title 字段
                .highlight(h -> h
                        .fields("title", f -> f
                                .preTags("<font color='red'>")
                                .postTags("</font>")))
                // 分页查询,从第 PageNo 页开始查询 PageSize 个 document
                .from(finalPageNo)
                .size(finalPageSize), Content.class
        );
        // 解析结果
        List<Map<String, Object>> list = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();
        for (Hit<Content> hit : searchResponse.hits().hits()) {
            Content content = hit.source();
            Map<String, Object> map = objectMapper.convertValue(content, new TypeReference<Map<String, Object>>() {
            });
            // 解析高亮字段
            Map<String, List<String>> highlightFields = hit.highlight();
            List<String> title = highlightFields.get("title");
            if (title != null) {
                map.put("title", title.get(0));
            }
            list.add(map);
        }
        return list;


    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
  1. 修改 index.html
<!--标题-->
<p class="productTitle">
    <a v-html="result.title"> </a>
</p>

参考资料

  1. ElasticSearch8.X 的 JavaApi 使用 - 掘金 (juejin.cn)
  2. ElasticSearch7.6.x 最新完整教程通俗易懂【狂神说 Java】

标签:实战,String,keyword,title,List,ElasticSearch,new,public
From: https://www.cnblogs.com/lockegogo/p/17401724.html

相关文章

  • Qt实战,50套纯源码不怕你学不会! QT_多线程生产制造MES 1,
    Qt实战,50套纯源码不怕你学不会!QT_多线程生产制造MES1,现场实战项目。2,这是一个汽车部件制造企业的一条厂线现场精密控制。3,由本人单独完成。设计技术众多,C++,PLC,OPC,工业以太网(扫码枪),串口扫码枪,多种数据库(多台设备)无缝连接与切换。与该公司内部MES无缝链接。4,提供yd码!6,OPENCV......
  • QT_C++多线程生产制造MES 1,现场实战项目。 2,这是一个汽车部件制
    QT_C++多线程生产制造MES1,现场实战项目。2,这是一个汽车部件制造企业的一条厂线现场精密控制。3,由本人单独完成。设计技术众多,C++,PLC,OPC,工业以太网(扫码枪),串口扫码枪,多种数据库(多台设备)无缝连接与切换。与该公司内部MES无缝链接。4,提供yd码!不懂的可以随时问卖主哦!工业编程!工业编......
  • elasticsearch安装
    一:下载地址https://www.elastic.co/cn/downloads/ 二:下载后上传到服务器 三:文件解压tar-zxvfelasticsearch-7.9.3-linux-x86_64.tar.gz 四:修改elasticsearch.yml #集群名,节点之间要保持一致cluster.name:my-application#节点名,集群内要唯一node.name:......
  • elasticsearch脚本查询
    脚本查询概念Scripting是Elasticsearch支持的一种专门用于复杂场景下支持自定义编程的强大的脚本功能,ES支持多种脚本语言,如painless,其语法类似于Java,也有注释、关键字、类型、变量、函数等,其就要相对于其他脚本高出几倍的性能,并且安全可靠,可以用于内联和存储脚本。支持的......
  • Netty实战(06)-ChannelPipeline 接口
    1概述把ChannelPipeline看成拦截流经Channel的入、出站事件的ChannelHandler的实例链,就易看出这些ChannelHandler之间的交互如何组成一个应用程序数据和事件处理逻辑的核心。每个新建的Channel都会被分配一个新的ChannelPipeline。这项关联是永久性的;Channel既不能附加另外......
  • Nacos 核心原理解读+高性能微服务系统实战-手撷芙蓉策虯驷
    Nacos核心原理解读+高性能微服务系统实战高性能微服务系统实战:构建稳定、高效的微服务架构关键字:微服务、高性能、系统实战、架构设计、容器化随着互联网的快速发展,越来越多的企业开始采用微服务架构来构建大型应用系统。相比于传统的单体架构,微服务架构具有更好的灵活性、可扩展......
  • 极客时间Go实战训练营1期16周-风雅不亡由善作
    极客时间Go实战训练营1期16周系统解析JDK源码:深入理解Java编程语言关键字:JDK源码、Java编程、系统解析、深入理解JDK是Java开发人员必备的开发工具包,其中包含了许多重要的类和接口,为Java编程提供了强大的支持。然而,对于一些高级开发人员来说,仅仅使用JDK提供的API可能不够满足需求,他......
  • 三菱FX3U与东元Teco变频器N310通讯实战程序 配件要求
    三菱FX3U与东元Teco变频器N310通讯实战程序配件要求:三菱FX3UPLC+FX3U485BD板,东元TecoN310变频器,昆仑通态触摸屏功能:采用485方式,modbusRTU协议,对N310变频器频率设定,正反转,频率,电压读取说明:是程序非实物,程序带有注释,昆仑通态触摸屏程序(附送威纶通触摸屏程序)。ID:6......
  • 西门子smart200与3台东元TECO N310变频器通讯实战程序 器
    西门子smart200与3台东元TECON310变频器通讯实战程序器件:西门子s7200smartPLC,3台东元TecoN310变频器,昆仑通态触摸屏(带以太网),中途可以加路由器控制方式:触摸屏与plc以太网通讯,PLC与变频器通讯485口相连功能:触摸屏控制变频器设定频率,启停,读取输出频率,电压说明:......
  • 台达DVP ES系列与3台东元Teco N310变频器通讯实战程序
    台达DVPES系列与3台东元TecoN310变频器通讯实战程序器件:台达DVPES系列的PLC,3台东元TecoN310系列变频器,昆仑通态功能:实现频率设定,启停控制,实际频率读取等。资料:带注释PLC程序,触摸屏程序,通讯设置说明,接线说明,变频器手册ID:9545671381738816......