springboot实现热搜后端elk

需求描述:热搜方式的分词查询。
数据环境:mysql中存在已爬数据表名t_bj(id,titile,content,publishtime),使用logstash同步到es中,springboot连接es实现rest接口给前端页面。

springboot

dom文件:

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.17.3</version></dependency>

yml文件:
elasticsearch:
uris: 192.168.0.1:9200
connection-timeout: 1s
socket-timeout: 30s

java文件:
RsController.java
@RestController
@RequestMapping(“/rs”)
public class RsController {
@Autowired
private TBjService tBjService;
@PostMapping(“/bjKey”)
public PageInfo getTLawEs(@RequestBody ReqKey reqKey) {
return tService.getTBj(reqKey.getKeyValue(),reqKey.getPageNum(),reqKey.getPageSize());
}
}

ReqKey.java
@Data
public class ReqKey {
private String keyValue;
private int pageNum;
private int pageSize;
}

TBj.java
@Data
@Document(indexName = “t_bj_index”)
public class TBj {
private String id;
private String title;
private String url;
private String content;
private String publishtime;
private String createtime;
}

RsConfig.java
@EnableElasticsearchRepositories(basePackages = {“cn.rs.elastic.repository”})
@Configuration
public class RsConfig {
@Value(“${spring.elasticsearch.uris}”)
private String hostAndPort;
@Bean
public RestHighLevelClient elasticsearchClient() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(hostAndPort)
.build();
return RestClients.create(clientConfiguration).rest();
}
}

TBjRepository.java
public interface TBjRepository extends ElasticsearchRepository<TBj, String> {
}

TBjService.java
@Service
public class TBjService {

private final TjRepository tBjRepository;
@Autowired
RsUtils rsUtils;
@Autowired
public TBjService(TBjRepository TBjRepository) {this.tBjRepository = TBjRepository;
}
public PageInfo<TBj> getTBj(String keywords, Integer pageNum, Integer pageSize) {SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();String[] queryFields = { "title"};QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keywords, queryFields).field("content", 2F).tieBreaker(0.3F);searchSourceBuilder.query(queryBuilder);List<String> highFields = ListUtil.toList(queryFields);highFields.add("content");return esUtils.page("t_bj_index", searchSourceBuilder, TBj.class, pageNum,pageSize, highFields);
}

}

RsUtils.java
package cn.rs.elastic.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageInfo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class EsUtils {
@Resource
private RestHighLevelClient restHighLevelClient;
public PageInfo page(String index, SearchSourceBuilder searchSourceBuilder, Class resultClass,
int currentPage, int size, List highFields) {
SearchRequest request = new SearchRequest(index);
if (CollectionUtil.isNotEmpty(highFields)) {
buildHighLight(searchSourceBuilder, highFields);
}
int num = (currentPage - 1) * size;
searchSourceBuilder.from(num)
.size(size);
request.source(searchSourceBuilder);
SearchResponse response = null;
try {
response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
assert response != null;
return analysisResponse(response, resultClass, currentPage, size, highFields);
}

private <T> PageInfo<T> analysisResponse(SearchResponse response, Class<T> resultClass, int currentPage, int size, List<String> highFields) {SearchHit[] searchHits = response.getHits().getHits();List<T> retList = new ArrayList<>(searchHits.length);for (SearchHit searchHit : searchHits) {String strJson = searchHit.getSourceAsString();T t = JSONUtil.toBean(strJson, resultClass);try {setId(resultClass, t, String.valueOf(searchHit.getId()));} catch (Exception e) {log.info("rs 查询数据设置主键id值异常", e);}if (!CollectionUtils.isEmpty(highFields)) {Map<String, HighlightField> highlightFieldMap = searchHit.getHighlightFields();HighlightField highlightField;for (String field : highFields) {highlightField = highlightFieldMap.get(field);if (highlightField != null) {Text[] fragments = highlightField.getFragments();StringBuilder builder = new StringBuilder();for (Text text : fragments) {builder.append(text);}setValue(resultClass, t, builder.toString(), field);}}}retList.add(t);}long totalNum = response.getHits().getTotalHits().value;PageInfo<T> pageVo = new PageInfo<>();pageVo.setPageNum(currentPage);pageVo.setPageSize(size);pageVo.setTotal(totalNum);pageVo.setList(retList);return pageVo;
}@SneakyThrows
private <T> void setId(Class<T> resultClass, T t, Object id) {Field field = ReflectionUtils.findField(resultClass, "id");if (null != field) {field.setAccessible(true);Object object = ReflectionUtils.getField(field, t);if (object == null) {Method method = resultClass.getMethod("setId", String.class);ReflectionUtils.invokeMethod(method, t, id);}}
}@SneakyThrows
private <T> void setValue(Class<T> resultClass, T t, Object fieldValue, String fieldName) {Field field = ReflectionUtils.findField(resultClass, fieldName);if (null != field) {field.setAccessible(true);String methodName = "set".concat(captureName(fieldName));Method method = resultClass.getMethod(methodName, String.class);ReflectionUtils.invokeMethod(method, t, fieldValue);}
}private String captureName(String str) {char[] cs = str.toCharArray();cs[0] -= 32;return String.valueOf(cs);
}private void buildHighLight(SearchSourceBuilder searchSourceBuilder, List<String> fields) {HighlightBuilder highlightBuilder = new HighlightBuilder();fields.forEach(highlightBuilder::field);highlightBuilder.preTags("<em>");highlightBuilder.postTags("</em>");searchSourceBuilder.highlighter(highlightBuilder);
}@AllArgsConstructor
@Data
public class ScrollPageBean<T> {private String scrollId;private PageInfo<T> scrollPage;
}

}

elasticSearch

作用:热搜引擎
1下载安装
2配置参数。conf/elasticsearch.yml
cluster.name: rs-single-node-cluster
node.name: rs-single-node
node.roles: [“master”, “data”]
path.data: /path/to/data
path.logs: /path/to/logs
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: [“sj-single-node”]
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl:
enabled: false
keystore.path: certs/http.p12
xpack.security.transport.ssl:
enabled: false
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
http.host: 0.0.0.0
transport.port: 9300
xpack.ml.enabled: false
http.cors.enabled: true
http.cors.allow-origin: “*”

2启动。bin/elasticsearch.bat
3启动成功默认端口9200,可录入http://127.0.0.1:9200 查看启动参数

logstash

作用:同步mysql数据到es,可指定同步策略如间隔时间等
1下载安装。
2配置mysql和es连接。
主目录下创建目录和文件mysql_rs_conf/mysql_rs.conf。并将驱动文件拷贝至该目录下。配置文件内容:
input {
jdbc {
jdbc_connection_string => “jdbc:mysql://192.168.1.1:3306/dbBj?useUnicode=true&useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true”
jdbc_user => “bj”
jdbc_password => “123456”
jdbc_driver_library => “D:/logstash/logstash-8.12.2/mysql_es_conf/mysql-connector-j-8.0.33.jar”
jdbc_driver_class => “com.mysql.jdbc.Driver”
jdbc_paging_enabled => “true”
jdbc_page_size => “10000”
statement => “select * from t_bj”
schedule => “* * * * *”
}
}

output {
if [table] == “t_bj” {
elasticsearch {
hosts => “192.168.1.36:9200”
index => “t_bj_index”
document_id => “%{id}”
}
}

stdout {
codec => json_lines
}
}

3启动。默认端口5601
可手创建启动文件lg.cmd。内容:
chcp 65001
logstash -f ./mysql_rs_conf/mysql_rs.conf
4验证与访问。

kinana

作用:可查看同步数据、测试、监控
1下载安装。
2配置指向ES。
3启动。默认端口5601
4验证与访问。URL:127.0.0.1:5601/app/integrations/browse
mysql

作用:热搜的中间过渡存储,用于存储爬虫数据。
建表:
CREATE TABLE t_bj (
id int(11) NOT NULL AUTO_INCREMENT,
title varchar(1000) NOT NULL COMMENT ‘文章标题’,
url varchar(1000) DEFAULT NULL COMMENT ‘文章地址’,
content longtext COMMENT ‘文章内容’,
publishtime varchar(30) DEFAULT NULL COMMENT ‘发布时间’,
createtime datetime DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,
PRIMARY KEY (id,title) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=492 DEFAULT CHARSET=utf8 COMMENT=‘保健’

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/770528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ruoyi若依框架下载流程详细解读(SpringBoot-Vue)

图解&#xff1a; 前端设计&#xff1a; 前端设计一个link文字连接或者按钮&#xff08;ElementUI&#xff09;Element - The worlds most popular Vue UI framework 前端请求设计&#xff1a; import request from /utils/request //下载示例模型定义语言的JSON export const…

零售商品计划新篇章:智能管理系统的挑战与机遇

在零售企业管理中&#xff0c;商品计划管理在零售企业运营中占据核心地位。面对日益激烈的市场竞争和消费者需求的多样化&#xff0c;零售企业在商品计划管理方面面临着诸多挑战和需求。以下针对这些挑战和需求的分析&#xff0c;以及对一套智能商品计划管理系统应具备的功能和…

基于SpringBoot IP黑白名单的实现2

业务场景 IP黑白名单是网络安全管理中常见的策略工具&#xff0c;用于控制网络访问权限&#xff0c;根据业务场景的不同&#xff0c;其应用范围广泛&#xff0c;以下是一些典型业务场景&#xff1a; 服务器安全防护&#xff1a; 黑名单&#xff1a;可以用来阻止已知的恶意IP地…

每日一练:LeeCode-200、岛屿数量【DFS递归+BFS队列】

给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外&#xff0c;你可以假设该网格的四条边…

特种兵旅游-扬州、南京Citywalk

一、扬州 Day01 西安咸阳机场->扬州泰州机场&#xff08;扬州地界但是离泰州也嘎嘎近&#xff09;->大运河博物馆&#xff08;需要提前预约&#xff01;&#xff09;&#xff08;超级震撼&#xff09; Day02 瘦西湖&#xff08;门票有点贵&#xff0c;但是蛮值得&#x…

【微服务】Eureka(服务注册,服务发现)

文章目录 1.基本介绍1.学前说明2.当前架构分析1.示意图2.问题分析 3.引出Eureka1.项目架构分析2.上图解读 2.创建单机版的Eureka1.创建 e-commerce-eureka-server-9001 子模块2.检查父子pom.xml1.子 pom.xml2.父 pom.xml 3.pom.xml 引入依赖4.application.yml 配置eureka服务5.…

【数据结构刷题专题】—— 二叉树

二叉树 二叉树刷题框架 二叉树的定义&#xff1a; struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(NULL), right(NULL); };1 二叉树的遍历方式 【1】前序遍历 class Solution { public:void traversal(TreeNode* node, vector&…

CI/CD 搭建jenkins基础测试环境构建项目(一)

Jenkins是一个开源的持续集成工具&#xff0c;可以帮助开发团队自动化构建、测试和部署他们的软件项目。通过Jenkins&#xff0c;开发团队可以实现快速、高效地交付软件&#xff0c;并及时发现和解决问题&#xff0c;从而提高团队的生产力和软件质量。持续集成/持续交付&#x…

后端常问面经之操作系统

请简要描述线程与进程的关系,区别及优缺点&#xff1f; 本质区别&#xff1a;进程是操作系统资源分配的基本单位&#xff0c;而线程是任务调度和执行的基本单位 在开销方面&#xff1a;每个进程都有独立的代码和数据空间&#xff08;程序上下文&#xff09;&#xff0c;程序之…

计算机网络面试题二

1.什么是计算机网络拓扑结构&#xff1f;计算机网络拓扑结构有哪五种基本形式&#xff1f; 计算机网络的拓扑结构是指网络中各个结点之间相互连接的几何形式。计算机网络拓扑结构的基本形式有&#xff1a;总线型网络、环形网络、星形网络、树形网络、网状网络。 2.什么是协议…

【【嵌入式开发 Linux 常用命令系列 1.4 -- grep -Ev 反向搜索】

文章目录 grep 的反向搜索 grep 的反向搜索 如果想从文件 a 中过滤掉包含字符串 “dash” 或 “tom” 的行&#xff0c;并将剩余的行写入到文件 b&#xff0c;可以使用 grep 命令配合正则表达式。使用 grep 的 -E 选项允许你指定一个扩展的正则表达式&#xff0c;而 -v 选项使…

C# 中Linq并行查询AsParallel 方法与Stopwatch类的理解与使用

AsParallel 是 C# 中的一个方法&#xff0c;它属于 System.Linq 命名空间下的 ParallelEnumerable 类。这个方法用于启用查询的并行执行。当你对一个数据集合执行 LINQ 查询时&#xff0c;通常这些查询是按顺序执行的。但是&#xff0c;当你调用 AsParallel 方法后&#xff0c;…

sql中添加数据的命令

SQL&#xff0c;全称是结构化查询语言&#xff08;Structured Query Language&#xff09;&#xff0c;是一种特殊目的的编程语言&#xff0c;主要用于数据库查询和程序设计。它允许用户存取数据、查询、更新和管理关系数据库系统。SQL是高级的非过程化编程语言&#xff0c;允许…

详解多模态 AI

2022 年 11 月&#xff0c;OpenAI 推出了 ChatGPT。它只用了几天时间就以其前所未有的能力席卷了世界。生成式人工智能革命已经开始&#xff0c;每个人都在问同一个问题&#xff1a;下一步是什么&#xff1f; 当时&#xff0c;ChatGPT 和许多其他由大型语言模型 &#xff08;L…

Acer宏碁暗影骑士擎AN515-58笔记本电脑工厂模式原厂Win11系统ISO镜像安装包下载

宏基AN515-58原装出厂OEM预装Windows11系统工厂包&#xff0c;恢复出厂时开箱状态一模一样&#xff0c;带恢复还原功能 链接&#xff1a;https://pan.baidu.com/s/1iCVSYtList-hPqbyTyaRqQ?pwdt2gw 提取码&#xff1a;t2gw 宏基原装系统自带所有驱动、NITROSENSE风扇键盘灯…

4.2 循环语句loop,等差数列求和

汇编语言 1. 循环语句loop loop指令的格式是&#xff1a;loop 标号&#xff0c;CPU执行loop指令的时候&#xff0c;要进行两部操作 cx cx - 1;判断cx中的值&#xff0c;不为0则转至标号处执行程序&#xff0c;如果为0则向下执行 循环使用loop来实现&#xff0c;循环次数存…

一文看尽Mac上运行Windows的所有可能:虚拟机、云电脑 更多

需求背景 大学期间我一直用的是windows,经历了从wind8到wind11的时代。 21年我转型干了产品,拿着surface、Thinkpad办公,生产力跟身边MacBook的同事相比大打折扣;于是我入手了一款macbook。一用上就回不了头,苹果的妙控键盘、触摸板真的是梦幻的办公组合。我本人也没有在…

04、Lua 数据类型

Lua 数据类型 Lua 数据类型nil&#xff08;空&#xff09;boolean&#xff08;布尔&#xff09;number&#xff08;数字&#xff09;string&#xff08;字符串&#xff09;table&#xff08;表&#xff09;function&#xff08;函数&#xff09;thread&#xff08;线程&#xf…

目标跟踪研究

我以前以为是靠高帧率实现目标识别的,现在才意识到目标跟踪也扮演着重要的角色 目录 1.目标跟踪问题简述2. 目标追踪综述3.目标跟踪-匈牙利匹配4.目标追踪-距离计算5.待续1.目标跟踪问题简述 目标跟踪 要实现跟踪,也就是需要了解前后帧之间的关系,那自然需要一个队列来保存…

vue中动态路由是什么该如何实现

在 Vue 中&#xff0c;动态路由是指根据不同的参数或条件&#xff0c;生成不同的路由配置。实现动态路由可以通过以下步骤&#xff1a; 1. **定义动态路由规则**&#xff1a; - 在路由配置文件&#xff08;通常是 router/index.js&#xff09;中&#xff0c;使用路由的 pat…