当前位置: 首页 > news >正文

黑马头条-day10

文章目录

  • app端文章搜索
    • 1、文章搜索
      • 1.1 ElasticSearch环境搭建
      • 1.2 索引库创建
        • ①需求分析
        • ②ES导入数据场景分析
        • ③创建索引和映射
      • 1.3 索引数据同步
        • ①app文章历史数据导入ES
        • ②文章实时数据导入ES
      • 1.4 文章搜索多条件复合查询
        • ①关键词搜索
        • ②搜索接口定义
    • 2、搜索历史记录
      • 2.1 需求说明
      • 2.2 数据存储说明
      • 2.1 异步保存搜索历史
        • ①实现思路
      • 2.2 查看搜索历史列表
        • ①接口定义
      • 2.3 删除搜索历史
    • 3、联想词查询
      • 需求分析
      • 3.1 联想词的来源
      • 3.2 联想词功能实现
        • 接口定义
        • 正则表达式说明


app端文章搜索

1、文章搜索

1.1 ElasticSearch环境搭建

1、启动ElasticSearch

docker start elasticsearch

2、启动Kibana

docker start kibana

3、kibana测试分词效果

1.2 索引库创建

①需求分析

在这里插入图片描述

  • 用户输入关键词 比如java只要文章titile、content包含此关键词就可以搜索出来,搜索黑马程序员能把黑马、程序员相关都搜索出来
  • 搜索的文章结果里词条要高亮显示
  • 用户点击搜索结果任意一条可查看文章详情
②ES导入数据场景分析

在这里插入图片描述

③创建索引和映射

搜索结果页面展示什么内容?

  • 标题
  • 布局
  • 封面图片
  • 发布时间
  • 作者名称
  • 文章id
  • 作者id
  • 静态url

哪些字段需要索引和分词?

  • 标题
  • 内容

使用Kibana添加映射
索引库名称:app_info_article

PUT /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": "keyword"},"title":{"type":"text","analyzer":"ik_max_word"},"content":{"type":"text","analyzer":"ik_max_word"}}}
}

1.3 索引数据同步

①app文章历史数据导入ES

1、创建es索引和映射
前面创建过了
2、文章微服务集成es功能
导入es服务的依赖
3、编写单元测试将历史状态正常的文章数据同步到es中
数据量特别少一次导入
数据量特别多分批导入,一次一两千条

mapper接口和sql语句

/**
* 查询es需要的全部文章数据* @return*/
List<SearchArticleVo> loadSearchArticleList();
<select id="loadSearchArticleList" resultType="com.heima.model.search.vos.SearchArticleVo">select aa.*, aacc.content from ap_article aaleft join ap_article_config aac on aa.id=aac.article_idLEFT JOIN ap_article_content aacc on aa.id = aacc.article_id
where aac.is_down=0 and aac.is_delete=0</select>

测试类代码

@Autowired
private RestHighLevelClient client;
/*** 将历史文章数据导入ES中*/
@Test
public void testImportES() throws IOException {// 1. 查询所有状态正常的文章列表List<SearchArticleVo> searchArticleVoList = apArticleMapper.loadSearchArticleList();// 2. 构建BulkRequest批量请求对象BulkRequest bulkRequest = new BulkRequest();// 3. 遍历文章列表逐一添加IndexRequestfor (SearchArticleVo searchArticleVo : searchArticleVoList) {IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.source(JSON.toJSONString(searchArticleVo), XContentType.JSON).id(String.valueOf(searchArticleVo.getId()));bulkRequest.add(indexRequest);}// 4. 执行restHighLevelClient的bulk批量插入文档请求BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);// 5. 获取响应结果数据并输出int status = bulk.status().getStatus();System.out.println("导入完成,响应状态码"+status);System.out.println("==============================================================================================");BulkItemResponse[] items = bulk.getItems();for (BulkItemResponse item : items) {String result = item.getResponse().getResult().getLowercase();System.out.println(result);}
}
②文章实时数据导入ES

跨服务调用的异步,要使用mq
在这里插入图片描述
生产者

kafka:bootstrap-servers: 192.168.200.130:9092producer:retries: 10key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializer
// 5. 封装es所需的数据转为JSON,生产到Kafka中
SearchArticleVo searchArticleVo = new SearchArticleVo();
BeanUtils.copyProperties(apArticle,searchArticleVo);
searchArticleVo.setStaticUrl(url);
searchArticleVo.setContent(contentStr);
String articleJson = JSON.toJSONString(searchArticleVo);
kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC,articleJson);

消费者

spring:kafka:bootstrap-servers: 192.168.200.130:9092consumer:group-id: ${spring.application.name}key-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializer
@Component
@Slf4j
public class ApArticleImportESListener {@Autowiredprivate RestHighLevelClient client;@KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)public void msg (ConsumerRecord<String,String> consumerRecord) {if (consumerRecord != null) {String articleJSON = consumerRecord.value();SearchArticleVo searchArticleVo = JSON.parseObject(articleJSON, SearchArticleVo.class);IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.source(articleJSON, XContentType.JSON).id(searchArticleVo.getId().toString());try {IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);String result = indexResponse.getResult().getLowercase();String desc = result.equals("created") ? "导入成功" : "导入失败";log.info("[异步导入APP文章到ES],导入结果:{}", desc);} catch (IOException e) {throw new RuntimeException(e);}}}
}

1.4 文章搜索多条件复合查询

①关键词搜索

在这里插入图片描述

②搜索接口定义

在这里插入图片描述

2、搜索历史记录

2.1 需求说明

在这里插入图片描述

  • 异步保存搜索记录
  • 默认查询10条搜索记录,按照搜索关键词的时间倒序
  • 可以删除搜索记录

2.2 数据存储说明

用户的搜索记录,需要给每一个用户都保存一份,数据量大,要求加载速度快,通常这样的数据存储到mongodb更合适,不建议直接存储到关系型数据库中

2.1 异步保存搜索历史

①实现思路

保存的数据量太大,不想同步影响效率,采用异步保存
在这里插入图片描述

@Service
@Slf4j
public class ApUserSearchServiceImpl implements ApUserSearchService {@Autowiredprivate MongoTemplate mongoTemplate;@Async("taskExecutor")@Overridepublic void insert(String keyword, Integer userId) {// 1. 查询搜索记录Query query = Query.query(Criteria.where("keyword").is(keyword).and("userId").is(userId));ApUserSearch apUserSearch = mongoTemplate.findOne(query, ApUserSearch.class);// 2. 如果搜索记录不存在,则保存搜索记录if (apUserSearch == null) {apUserSearch = new ApUserSearch();SnowflakeIdWorker isWorker = new SnowflakeIdWorker(10, 10);apUserSearch.setId(isWorker.nextId());// 使用雪花算法的值当做主键IDapUserSearch.setUserId(userId);apUserSearch.setKeyword(keyword);apUserSearch.setIsDeleted(0); // 未删除apUserSearch.setCreatedTime(new Date());apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);return;}// 3. 如果搜索记录存在且未删除,则更新updatedTimeif (apUserSearch.getIsDeleted() == 0) {apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);return;}// 4. 如果搜索记录存在且已删除,则更新为未删除及更新updateTimeapUserSearch.setIsDeleted(0);apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);}
}

2.2 查看搜索历史列表

①接口定义

按照当前用户,按照时间倒序查询
在这里插入图片描述

@Overridepublic ResponseResult findUserSearch() {// 根据条件查询搜索记录列表(条件:userId和isDeleted 结果:updateTime倒序)Query query = Query.query(Criteria.where("userId").is(ThreadLocalUtil.getUserId()).and("isDeleted").is(0)).with(Sort.by(Sort.Direction.DESC,"updateTime"));query.limit(10);List<ApUserSearch> apUserSearchList = mongoTemplate.find(query, ApUserSearch.class);return ResponseResult.okResult(apUserSearchList);}

2.3 删除搜索历史

根据搜索历史id删除
在这里插入图片描述

@Overridepublic ResponseResult delUserSearch(HistorySearchDto dto) {ApUserSearch apUserSearch = mongoTemplate.findById(dto.getId(), ApUserSearch.class);if (apUserSearch == null) {return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"搜索记录不存在");}// 更新记录为已删除apUserSearch.setIsDeleted(1);apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}

3、联想词查询

需求分析

根据用户输入的关键字展示联想词
在这里插入图片描述

3.1 联想词的来源

通常是网上搜索频率比较高的一些词,通常在企业中有两部分来源:
第一:自己维护搜索词
通过分析用户搜索频率较高的词,按照排名作为搜索词

第二:第三方获取
关键词规划师(百度)、5118、爱站网

3.2 联想词功能实现

接口定义

在这里插入图片描述

正则表达式说明

在这里插入图片描述

@Service
@Slf4j
public class ApAssociateWordsServiceImpl implements ApAssociateWordsService {@Autowiredprivate MongoTemplate mongoTemplate;@Overridepublic ResponseResult search(UserSearchDto dto) {// 替换一切特殊字符dto.setSearchWords(dto.getSearchWords().replaceAll("[^\u4e00-\u9fa5a-zA-z0-9]", ""));List<ApAssociateWords> apAssociateWordsList = mongoTemplate.find(Query.query(Criteria.where("associateWords").regex(".*?\\" + dto.getSearchWords() + ".*")).limit(dto.getPageSize()), ApAssociateWords.class);return ResponseResult.okResult(apAssociateWordsList);}
}

相关文章:

黑马头条-day10

文章目录 app端文章搜索1、文章搜索1.1 ElasticSearch环境搭建1.2 索引库创建①需求分析②ES导入数据场景分析③创建索引和映射 1.3 索引数据同步①app文章历史数据导入ES②文章实时数据导入ES 1.4 文章搜索多条件复合查询①关键词搜索②搜索接口定义 2、搜索历史记录2.1 需求说…...

C++的stack容器->基本概念、常见接口

#include<iostream> using namespace std; #include <stack> //栈stack容器常用接口 void test01() { //创建栈容器 栈容器必须符合先进后出 stack<int> s; //向栈中添加元素&#xff0c;叫做 压栈 入栈 s.push(10); s.push(20); s…...

VUE中引入外部jquery.min.js文件

jquery官网&#xff1a;https://jquery.com/ cdn链接&#xff1a;https://code.jquery.com/jquery-3.7.1.js <template><div class"">测试jq<div id"jq">这是一个盒子</div></div> </template><script> import…...

MongoDB聚合运算符:$avg

$avg运算符返回给定数值的平均值 $avg可用于以下阶段&#xff1a; $addFields阶段(从MongoDB 3.4开始可用)$bucket阶段$bucketAuto阶段$group阶段包含$expr表达式的$match阶段$project阶段$replaceRoot阶段(从MongoDB 3.4开始可用)$replaceWith阶段(从MongoDB 4.2开始可用)$s…...

Web 前端 UI 框架Bootstrap简介与基本使用

Bootstrap 是一个流行的前端 UI 框架&#xff0c;用于快速开发响应式和移动设备优先的网页。它由 Twitter 的设计师和工程师开发&#xff0c;现在由一群志愿者维护。Bootstrap 提供了一套丰富的 HTML、CSS 和 JavaScript 组件&#xff0c;可以帮助开发者轻松地构建和定制网页和…...

【Python笔记-设计模式】惰性评价模式

一、说明 将某些对象的创建或计算延迟到真正需要它们的时候&#xff0c;以减少不必要的资源消耗和提高性能。 惰性评价在Python中实现也成为生成器&#xff0c;一般通过yield关键字实现。 (一) 解决问题 在处理大量数据时&#xff0c;使用惰性加载可以避免一次性加载所有数…...

每日学习总结20240221

每日总结 20240221 花自飘零水自流。一种相思&#xff0c;两处闲愁。 —— 李清照「一剪梅红藕香残玉簟秋」 1. stat 在Linux中&#xff0c;stat 是一个用于显示文件或文件系统状态的命令行工具。它提供了关于文件的详细信息&#xff0c;包括文件类型、权限、大小、所有者、修…...

学生成绩管理系统(C语言课设 )

这个学生成绩管理系统使用C语言编写&#xff0c;具有多项功能以方便管理学生信息和成绩。首先从文件中读取数据到系统中&#xff0c;并提供了多种功能&#xff08;增删改查等&#xff09;选项以满足不同的需求。 学生成绩管理系统功能: 显示学生信息增加学生信息删除学生信息…...

ChatGPT提示词(最新)

它能干什么? 包括但不限于&#xff1a; 类别描述学术论文它可以写各种类型的学术论文&#xff0c;包括科技论文、文学论文、社科论文等。它可以帮助你进行研究、分析、组织思路并编写出符合学术标准的论文。创意写作它可以写小说、故事、剧本、诗歌等创意性的文学作品&#…...

算法——模拟

1. 什么是模拟算法&#xff1f; 官方一点来说 模拟算法&#xff08;Simulation Algorithm&#xff09;是一种通过模拟现实或抽象系统的运行过程来研究、分析或解决问题的方法。它通常涉及创建一个模型&#xff0c;模拟系统中的各种事件和过程&#xff0c;以便观察系统的行为&a…...

如何进行高性能架构的设计

一、前端优化 减少请求次数页面静态化边缘计算 增加缓存控制&#xff1a;请求头 减少图像请求次数&#xff1a;多张图片变成 一张。 减少脚本的请求次数&#xff1a;css和js压缩&#xff0c;将多个文件压缩成一个文件。 二、页面静态化 三、边缘计算 后端优化 从三个方面进…...

vivado FSM Components

Vivado合成功能 •同步有限状态机&#xff08;FSM&#xff09;组件的特定推理能力。 •内置FSM编码策略&#xff0c;以适应您的优化目标。 •FSM提取默认启用。 •使用-fsm_extraction off可禁用fsm提取。 FSM描述 Vivado综合支持Moore和Mealy中的有限状态机&#xff08;…...

从零开始手写mmo游戏从框架到爆炸(十五)— 命令行客户端改造

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 到现在&#xff0c;我们切实需要一个客户端来完整的进行英雄选择&#xff0c;选择地图&#xff0c;打怪等等功能。所以我们需要把之前极为简陋的客户端改造一下。 首先…...

Elasticsearch:什么是 kNN?

kNN - K-nearest neighbor 定义 kNN&#xff08;即 k 最近邻算法&#xff09;是一种机器学习算法&#xff0c;它使用邻近度将一个数据点与其训练并记忆的一组数据进行比较以进行预测。 这种基于实例的学习为 kNN 提供了 “惰性学习&#xff08;lazy learning&#xff09;” 名…...

掌握网络未来:深入解析RSVP协议及其在确保服务质量中的关键作用

第一部分&#xff1a;RSVP简介 资源预留协议&#xff08;RSVP&#xff09;是一种网络协议&#xff0c;用于在网络中的各个节点之间预留资源&#xff0c;以支持数据流的服务质量&#xff08;QoS&#xff09;要求。RSVP特别适用于需要固定带宽和处理延迟的应用&#xff0c;如视频…...

【Linux】一站式教会:Ubuntu(无UI界面)使用apache-jmeter进行压测

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、Java…...

Howler.js:音频处理的轻量级解决方案

文章目录 Howler.js&#xff1a;音频处理的轻量级解决方案引言一、Howler.js简介1.1 特性概览 二、Howler.js基本使用使用详解2.1 创建一个Howl对象2.2 控制音频播放2.3 监听音频事件 三、进阶功能3.1 音频Sprites3.2 3D音频定位 四、微前端场景下的Howler.js Howler.js&#x…...

【讨论】Web端测试和App端测试的不同,如何说得更有新意?

Web 端测试和 App 端测试是针对不同平台的上的应用进行测试&#xff0c;Web应用和App端的应用实现方式不同&#xff0c;测试时的侧重点也不一样。 Web端应用和App端应用的区别&#xff1a; 平台兼容性 安装方式 功能和性能 用户体验 更新和维护 测试侧重点有何不同 平台…...

运维SRE-18 自动化批量管理-ansible4

12.2handles handles触发器(条件)&#xff0c;满足条件后再做什么事情应用场景&#xff1a;想表示&#xff1a;配置文件变化&#xff0c;再重启服务 配置handlers之前&#xff0c;每次运行剧本都会重启nfs&#xff0c;无论配置文件是否变化。 [rootm01 /server/ans/playbook]…...

编程笔记 Golang基础 008 基本语法规则

编程笔记 Golang基础 008 基本语法规则 Go语言的基本语法规则. Go语言的基本语法规则包括但不限于以下要点&#xff1a; 标识符&#xff1a; 标识符用于命名变量、常量、类型、函数、包等。标识符由字母&#xff08;a-z&#xff0c;A-Z&#xff09;、数字&#xff08;0-9&#…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...