个人网站的留言板怎么做/医院网络销售要做什么
JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb
- elasticsearch
- 安装配置
- app文章搜索
- 创建索引库
- app文章搜索
- 思路分析
- 具体实现
- 新增文章创建索引
- 思路分析
- 具体实现
- MongoDB
- 安装配置
- SpringBoot集成MongoDB
- app文章搜索记录
- 保存搜索记录
- 思路分析
- 具体实现
- 查询搜索历史
- 删除搜索历史
- 搜索联想词
- 来源
- Gitee
elasticsearch
安装配置
https://blog.csdn.net/Y_cen/article/details/131856995
app文章搜索
创建索引库
- 使用postman添加映射
Put请求, Json格式 : http://192.168.174.133:9200/app_info_article{"mappings":{"properties":{"id":{"type":"long"},"publishTime":{"type":"date"},"layout":{"type":"integer"},"images":{"type":"keyword","index": false},"staticUrl":{"type":"keyword","index": false},"authorId": {"type": "long"},"authorName": {"type": "text"},"title":{"type":"text","analyzer":"ik_smart"},"content":{"type":"text","analyzer":"ik_smart"}}} }
- 依赖
<!--elasticsearch--> <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.12.1</version> </dependency> <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.12.1</version> </dependency> <dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.12.1</version> </dependency>
- 导入数据
@Autowired private ApArticleMapper apArticleMapper;@Autowired private RestHighLevelClient restHighLevelClient;/*** 注意:数据量的导入,如果数据量过大,需要分页导入* @throws Exception*/ @Test public void init() throws Exception {// 1. 查询所有符合条件的文章数据List<SearchArticleVo> searchArticleVos = apArticleMapper.loadArticleList();// 2. 批量导入到es索引库BulkRequest bulkRequest = new BulkRequest("app_info_article");for (SearchArticleVo searchArticleVo : searchArticleVos) {IndexRequest indexRequest = new IndexRequest().id(searchArticleVo.getId().toString()).source(JSON.toJSONString(searchArticleVo), XContentType.JSON);// 批量添加数据bulkRequest.add(indexRequest);}restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); }
app文章搜索
思路分析
具体实现
- 配置
没有使用数据库, 所以无需数据源的自动配置spring:autoconfigure:exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration elasticsearch:host: 192.168.174.133port: 9200
- 业务代码
@Service public class ArticleSearchServiceImpl implements ArticleSearchService {@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** es文章分页检索* @param dto* @return*/@Overridepublic ResponseResult search(UserSearchDto dto) throws IOException {// 1. 检查参数if(dto == null || StringUtils.isBlank(dto.getSearchWords())){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 2. 设置查询条件SearchRequest searchRequest = new SearchRequest("app_info_article");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 布尔查询BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();// 2.1 关键字的分词之后查询QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);boolQueryBuilder.must(queryStringQueryBuilder);// 2.2 查询小于mindate的数据RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime());boolQueryBuilder.filter(rangeQueryBuilder);// 2.3 分页查询searchSourceBuilder.from(0);searchSourceBuilder.size(dto.getPageSize());// 2.4 按照发布时间倒序查询searchSourceBuilder.sort("publishTime", SortOrder.DESC);// 2.5 设置高亮 titleHighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title");highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");highlightBuilder.postTags("</font>");searchSourceBuilder.highlighter(highlightBuilder);searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 3. 结果封装返回List<Map> list = new ArrayList();SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {String json = hit.getSourceAsString();Map map = JSON.parseObject(json, Map.class);// 处理高亮if(hit.getHighlightFields() != null && hit.getHighlightFields().size() > 0){Text[] titles = hit.getHighlightFields().get("title").getFragments();String title = StringUtils.join(titles);// 高亮标题map.put("h_title", title);}else{// 原始标题map.put("h_title", map.get("title"));}list.add(map);}return ResponseResult.okResult(list);} }
- 网关配置
app端网关#搜索微服务 - id: leadnews-searchuri: lb://leadnews-searchpredicates:- Path=/search/**filters:- StripPrefix= 1
新增文章创建索引
思路分析
具体实现
- Producer
SearchArticleVo需要静态地址, 所以需要在FreeMarker生成静态文章, 上传到MinIo之后再发送创建索引的消息@Service @Slf4j @Transactional public class ArticleFreemarkerServiceImpl implements ArticleFreemarkerService {...@Override@Asyncpublic void buildArticleToMinIO(ApArticle article, String content) {if(StringUtils.isNotBlank(content)) {...// kafka: 新增文章创建索引, 发送消息createArticleESIndex(article, content, path);}}@Autowiredprivate KafkaTemplate<String, String> kafkaTemplate;private void createArticleESIndex(ApArticle article, String content, String path) {SearchArticleVo searchArticleVo = new SearchArticleVo();BeanUtils.copyProperties(article, searchArticleVo);searchArticleVo.setContent(content);searchArticleVo.setStaticUrl(path);kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSON.toJSONString(searchArticleVo));} }
- Listener
@Component @Slf4j public class SyncArticleListener {@Autowiredprivate RestHighLevelClient restHighLevelClient;@KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)public void onMessage(String message){if(StringUtils.isNotBlank(message)){log.info("SyncArticleListener, message={}", message);SearchArticleVo vo = JSON.parseObject(message, SearchArticleVo.class);IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.id(vo.getId().toString());indexRequest.source(message, XContentType.JSON);try {restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);} catch (IOException e) {log.error("sync es error={}", e);throw new RuntimeException(e);}}}}
MongoDB
安装配置
# 拉取镜像
docker pull mongo
# 创建容器
docker run -di --name mongo -p 27017:27017 -v ~/data/mongodata:/data mongo
SpringBoot集成MongoDB
- 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
- 配置
spring:data:mongodb:host: 192.168.174.133port: 27017database: leadnews-history
- 使用
public class MongoTest {@Autowiredprivate MongoTemplate mongoTemplate;//保存@Testpublic void saveTest(){ApAssociateWords apAssociateWords = new ApAssociateWords();apAssociateWords.setAssociateWords("黑马头条");apAssociateWords.setCreatedTime(new Date());mongoTemplate.save(apAssociateWords);}//查询一个@Testpublic void saveFindOne(){ApAssociateWords apAssociateWords = mongoTemplate.findById("64e46fd4f3a760442bf50527", ApAssociateWords.class);System.out.println(apAssociateWords);}//条件查询@Testpublic void testQuery(){Query query = Query.query(Criteria.where("associateWords").is("黑马头条")).with(Sort.by(Sort.Direction.DESC,"createdTime"));List<ApAssociateWords> apAssociateWordsList = mongoTemplate.find(query, ApAssociateWords.class);System.out.println(apAssociateWordsList);}@Testpublic void testDel(){mongoTemplate.remove(Query.query(Criteria.where("associateWords").is("黑马头条")),ApAssociateWords.class);} }
app文章搜索记录
保存搜索记录
思路分析
异步保存
保存数据
具体实现
public class ApUserSearchServiceImpl implements ApUserSearchService {@Autowiredprivate MongoTemplate mongoTemplate;/*** 保存用户搜索记录* @param keyword* @param userId*/@Override@Asyncpublic void insert(String keyword, Integer userId) {// 1. 查询当前用户的搜索关键词Query query = Query.query(Criteria.where("userId").is(userId).and("keyword").is(keyword));ApUserSearch apUserSearch = mongoTemplate.findOne(query, ApUserSearch.class);// 2. 存在, 更新创建时间if(apUserSearch != null){apUserSearch.setCreatedTime(new Date());mongoTemplate.save(apUserSearch);return;}// 3. 不存在, 判断当前历史记录总数量是否超过10apUserSearch = new ApUserSearch();apUserSearch.setUserId(userId);apUserSearch.setKeyword(keyword);apUserSearch.setCreatedTime(new Date());Query query1 = Query.query(Criteria.where("userId").is(userId));query1.with(Sort.by(Sort.Direction.DESC, "createTime"));List<ApUserSearch> apUserSearchList = mongoTemplate.find(query1, ApUserSearch.class);if(apUserSearchList == null || apUserSearchList.size() < 10){mongoTemplate.save(apUserSearch);}else{ApUserSearch lastUserSearch = apUserSearchList.get(apUserSearchList.size() - 1);mongoTemplate.findAndReplace(Query.query(Criteria.where("id").is(lastUserSearch.getId())), apUserSearch);}}
}
在文章搜索中调用, 因为未登录也可能有token(游客), 所以需要判断是否登录.
ApUser user = AppThreadLocalUtil.getUser();
// 异步调用, 保存搜索记录
if(user!=null && dto.getFromIndex() == 0){apUserSearchService.insert(dto.getSearchWords(), user.getId());
}
查询搜索历史
public ResponseResult findUserSearch() {// 获取当前用户ApUser user = AppThreadLocalUtil.getUser();if(user == null){return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}// 根据用户查询数据, 根据时间排序Query query = Query.query(Criteria.where("userId").is(user.getId()));query.with(Sort.by(Sort.Direction.DESC, "createdTime"));List<ApUserSearch> apUserSearchList = mongoTemplate.find(query, ApUserSearch.class);return ResponseResult.okResult(apUserSearchList);
}
删除搜索历史
public ResponseResult delUserSearch(HistorySearchDto dto) {// 检查参数if(dto.getId() == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 获取当前用户ApUser user = AppThreadLocalUtil.getUser();if(user == null){return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}// 删除Query query = Query.query(Criteria.where("id").is(dto.getId()).and("userId").is(user.getId()));mongoTemplate.remove(query, ApUserSearch.class);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
搜索联想词
public class ApAssociateWordsServiceImpl implements ApAssociateWordsService {@Autowiredprivate MongoTemplate mongoTemplate;/*** 搜索联想词* @param dto* @return*/@Overridepublic ResponseResult search(UserSearchDto dto) {// 1. 检查参数if(StringUtils.isBlank(dto.getSearchWords())){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 2. 分页检索if(dto.getPageSize() > 20){dto.setPageSize(20);}// 3. 执行查询, 模糊查询Query query = Query.query(Criteria.where("associateWords").regex(".*?\\" + dto.getSearchWords() + ".*"));query.limit(dto.getPageSize());List<ApAssociateWords> apAssociateWordsList = mongoTemplate.find(query, ApAssociateWords.class);return ResponseResult.okResult(apAssociateWordsList);}
}
来源
黑马程序员. 黑马头条
Gitee
https://gitee.com/yu-ba-ba-ba/leadnews
相关文章:

JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb
JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb elasticsearch安装配置 app文章搜索创建索引库app文章搜索思路分析具体实现 新增文章创建索引思路分析具体实现 MongoDB安装配置SpringBoot集成MongoDB app文章搜索记录保存搜索记录思路分析具体实现 查询搜索历史删除搜索历史 搜…...

redux中间件理解,常见的中间件,实现原理。
文章目录 一、Redux中间件介绍1、什么是Redux中间件2、使用redux中间件 一、Redux中间件介绍 1、什么是Redux中间件 redux 提供了类似后端 Express 的中间件概念,本质的目的是提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 actio…...

麒麟系统上安装 MySQL 8.0.24
我介绍一下在麒麟系统上安装 MySQL 8.0.24 的详细步骤,前提是您已经下载了 mysql-8.0.24-linux-glibc2.12-x86_64.tar.xz 安装包。其实安装很简单,但是有坑,而且问题非常严重!由于麒麟系统相关文章博客较少,导致遇到了…...

vue 展开和收起
效果图 代码块 <div><span v-for"(item,index) in showHandleList" :key"item.index"><span>{{item.emailFrom}}</span></span><span v-if"this.list.length > 4" click"showAll !showAll">{…...

限制立方样条(RCS)中的P for overall和P for nonlinear的计算
最近不少人私信我,说有些SCI文章报了两个P值一个是P for overall,一个是P for nonlinear,就像下图这样,问我P for overall怎么计算。 P for overall我也不清楚是什么,有些博主说这个是总效应的P值,但是我没有找到相关出处。但是怎…...

vue3+ts引入echarts并实现自动缩放
第一种写法(不支持随页面大小变化而缩放) 统一的HTML页面 <div class"content_box" ref"barChart" id"content_box"></div>TS语法 <script setup lang"ts">import * as echarts from echar…...

Compressor For Mac强大视频编辑工具 v4.6.5中文版
Compressor for Mac是苹果公司推出的一款视频压缩工具,可以将高清视频、4K视频、甚至是8K视频压缩成适合网络传输或存储的小文件。Compressor支持多种视频格式,包括H.264、HEVC、ProRes和AVC-Intra等,用户可以根据需要选择不同的压缩格式。 …...

maven工程的目录结构
https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html maven工程的目录结构: 在maven工程的根目录下面,是pom.xml文件。此外,还有README.txt、LICENSE.txt等文本文件,便于用户能够…...

5.1 webrtc线程模型
那从今天开始呢?我们来了解一下y8 tc线程相关的内容,那在开始之前呢?我们先来看一下,我们本章都要讲解哪些知识? 那第一个呢?是线程的基础知识,这块内容呢?主要是为大家做一下回顾&a…...

【Linux网络】Cookie和session的关系
目录 一、Cookie 和 session 共同之处 二、Cookie 和 session 区别 2.1、cookie 2.2、session 三、cookie的工作原理 四、session的工作原理 一、Cookie 和 session 共同之处 Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式。 二、Cookie 和 session 区别 2.…...

android 硬编码保存mp4
目录 java imagereader编码保存 java NV21toYUV420SemiPlanar 编码保存视频用: imageReader获取nv21 代码来自博客: 【Android Camera2】彻底弄清图像数据YUV420_888转NV21问题/良心教学/避坑必读!_yuv420888转nv21_奔跑的鲁班七号的博客-CSDN博客 …...

gitlab合并分支
我的分支为 cheng 第一步: 增加新的代码 第二步:提交并推送 第三步:打开gitlab,找到对应项目 这样就成功把cheng分支合并到dev-test分支了...

手撕 `np.transpose` : 三维数组的循环转置
手撕 np.transpose : 三维数组的循环转置 手撕 np.transpose 2D 何为transpose ? 如上图: 二维的例子, 直观地理解就是沿着对角线拉平(对角关系左上右下依旧), 其他位置依次填充. 2. 2D数组中0,1 为原始参, 1,0 为转置参 - 原始参即数组的原始形态: 比如👆&#x…...

计算机竞赛 基于Django与深度学习的股票预测系统
文章目录 0 前言1 课题背景2 实现效果3 Django框架4 数据整理5 模型准备和训练6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于Django与深度学习的股票预测系统 ** 该项目较为新颖,适合作为竞赛课题方向ÿ…...

CSS 小技能(一):HTML 两个图片竖着平铺、设置图片点击、设置滚动条颜色
下面的代码没有考虑响应式的效果,如果考虑的话还需要一些代码进行处理。 【注】当时写的时候仅考虑了 webkit 内核的浏览器,如果是 IE 或者其他浏览器,请增加额外的 CSS 样式进行控制。 <!DOCTYPE html> <html> <head>&l…...

【论文阅读】CONAN:一种实用的、高精度、高效的APT实时检测系统(TDSC-2020)
CONAN:A Practical Real-Time APT Detection System With High Accuracy and Efficiency TDSC-2020 浙江大学 Xiong C, Zhu T, Dong W, et al. CONAN: A practical real-time APT detection system with high accuracy and efficiency[J]. IEEE Transactions on Dep…...

P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布
题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种石头剪刀布的升级版游戏。 升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势: 斯波克:《星际迷航》主…...

基于Android水果蔬菜果蔬到家商城系统 微信小程序uniAPP的开发与实现
果蔬到家是商家针对用户必不可少的一个部分。在商铺发展的整个过程中,果蔬到家担负着最重要的角色。为满足如今日益复杂的管理需求,各类果蔬到家程序也在不断改进。本课题所设计的springboot基于HBuilder X的果蔬到家APP,使用SpringBoot框架&…...

【Python】从入门到上头—Python基础(2)
文章目录 一.基础语法1.编码2.标识符3.保留字4.注释5.行与缩进6.多行语句7.数字(Number)类型8.字符串(String)9.空行10.等待用户输入11.同一行显示多条语句12.多个语句构成代码组13.print 输出14.import 与 from...import 二.基本数据类型1.变量和赋值2.多个变量赋值3.标准数据…...

leetcode刷题之283:移动零
问题 实现思路 首先, 将dest指向-1 位置, cur指向下标为0 的位置, 在cur遍历的过程中: 1) 遇到非零元素则与下标dest1 位置的元素交换, 2) 若遇到零元素则只继续cur遍历. 下标为1 的位置上是 非零元素 执行1) 交换得到右图结果 随后cur 得到下图结果 下标为2 的位置上是零…...

【Spring Boot】SpringBoot和数据库交互: 使用Spring Data JPA
文章目录 1. 数据库和Java应用程序1.1 为什么需要数据库交互1.2 传统的数据库交互方法 2. 什么是JPA2.1 JPA的定义2.2 JPA的优势 3. Spring Data JPA介绍3.1 Spring Data JPA的特性3.2 如何简化数据库操作 4. 在SpringBoot中集成Spring Data JPA4.1 添加依赖4.2 配置数据源 5. …...

自动化部署及监测平台基本架构
声明 本文是学习 政务计算机终端核心配置规范. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 核心配置自动化部署及监测技术要求 自动化部署及监测平台基本架构 对于有一定规模的政务终端核心配置应用,需要配备自动化部署及监测平台&am…...

基于NXP i.MX 6ULL核心板的物联网模块开发案例(1)
目录 前 言 1 SDIO WIFI模块测试 1.1 STA模式测试 1.2 AP模式测试 1.3 SDIO WIFI驱动编译 前言 本文主要介绍基于创龙科技TLIMX6U-EVM评估板的物联网模块开发案例,适用开发环境: Windows开发环境:Windows 7 64bit、Windows 10 64bit …...

【路由器】小米 WR30U 解锁并刷机
文章目录 解锁 ssh环境准备解锁过程 刷入 mt798x uboot简介刷入流程 刷入 ImmortalWrt简介刷入流程 刷为原厂固件参考资料 本文主要记录个人对小米 WR30U 路由器的解锁和刷机过程,整体步骤与 一般安装流程 类似,但是由于 WR30U 的解锁 ssh 和刷机的过程中…...

数据库操作语句
一,SQL分类 DDL:数据定义语言 DML:数据操纵语言 DQL:数据查询语言 DCL:数据控制语言 创建数据库和表 #创建数据库 create database 数据库名; #创建数据表 create table 表名 (字段1 字段1类型(字段长度) 字段限制,字…...

Mr. Cappuccino的第64杯咖啡——Spring循环依赖问题
Spring循环依赖问题 什么是循环依赖问题示例项目结构项目代码运行结果 Async注解导致的问题使用Lazy注解解决Async注解导致的问题开启Aop使用代理对象示例项目结构项目代码运行结果 Spring是如何解决循环依赖问题的原理源码解读 什么情况下Spring无法解决循环依赖问题 什么是循…...

Adapting Language Models to Compress Contexts
本文是LLM系列文章,针对《Adapting Language Models to Compress Contexts》的翻译。 使语言模型适应上下文压缩 摘要1 引言2 相关工作3 方法4 实验5 上下文学习6 压缩检索语料库实现高效推理7 结论不足 摘要 1 引言 2 相关工作 3 方法 4 实验 5 上下文学习 …...

Kubernetes(K8S)使用PV和PVC做存储安装mysql
Kubernetes使用PV和PVC做存储安装mysql 环境准备什么是PV和PVC环境准备配置nfs安装nfs配置nfs服务端 创建命名空间配置pv和pvcpv的yaml文件pvc的yaml文件 部署mysql创建mysql的root密码的secret创建mysql部署的yaml部署mysql链接mysql外部链接内部链接 环境准备 首先你需要一个…...

Ansible Playbook 常用变量
以下是 Ansible Playbook 常用变量 ansible_connection: 指定连接类型(如 ssh、winrm) ansible_user: 指定远程用户 ansible_ssh_pass: 指定远程用户密码 ansible_become: 指定是否切换为超级用户 ansible_become_user: 指定切换到的用户 ansible_b…...

0103水平分片-jdbc-shardingsphere-中间件
文章目录 1 准备服务器1.1 创建server-order0容器1.2 创建server-order1容器 2、基本水平分片2.1、基本配置2.2、数据源配置2.3、标椎分片表配置2.4、行表达式2.5、分片算法配置2.6、分布式序列算法 3、多表关联3.1、创建关联表3.2、创建实体类3.3、创建Mapper3.4、配置关联表3…...